代码之家  ›  专栏  ›  技术社区  ›  Purfideas

为什么Ruby setter在类中需要“自我”资格认证?

  •  67
  • Purfideas  · 技术社区  · 17 年前

    Ruby setters–是否由 (c)attr_accessor 或者手动检测是唯一需要的方法 self. 在类本身中访问时的限定。这似乎让Ruby在语言世界中独占鳌头:

    • 所有方法都需要 self / this
    • 不需要任何方法
    • 只有二传手需要 自己 /

    最好的比较是C#与Ruby,因为这两种语言都支持语法上与类实例变量类似的访问器方法: foo.x = y , y = foo.x . C#称之为属性。

    这里有一个简单的例子;Ruby和C#中的相同程序:

    class A
      def qwerty; @q; end                   # manual getter
      def qwerty=(value); @q = value; end   # manual setter, but attr_accessor is same 
      def asdf; self.qwerty = 4; end        # "self." is necessary in ruby?
      def xxx; asdf; end                    # we can invoke nonsetters w/o "self."
      def dump; puts "qwerty = #{qwerty}"; end
    end
    
    a = A.new
    a.xxx
    a.dump
    

    拿走 self.qwerty =() 它失败了(Linux和OS X上的Ruby 1.8.6)。现在C#:

    using System;
    
    public class A {
      public A() {}
      int q;
      public int qwerty {
        get { return q; }
        set { q = value; }
      }
      public void asdf() { qwerty = 4; } // C# setters work w/o "this."
      public void xxx()  { asdf(); }     // are just like other methods
      public void dump() { Console.WriteLine("qwerty = {0}", qwerty); }
    }
    
    public class Test {
      public static void Main() {
        A a = new A();
        a.xxx();
        a.dump();
      }
    }
    

    问:这是真的吗?除了二传,还有其他需要自我的场合吗?也就是说,是否有其他情况下使用Ruby方法 不能 没有 自己

    当然,在很多情况下,自我保护 必需的这并不是Ruby所独有的,只是要明确一点:

    using System;
    
    public class A {
      public A() {}
      public int test { get { return 4; }}
      public int useVariable() {
        int test = 5;
        return test;
      }
      public int useMethod() {
        int test = 5;
        return this.test;
      }
    }
    
    public class Test {
      public static void Main() {
        A a = new A();
        Console.WriteLine("{0}", a.useVariable()); // prints 5
        Console.WriteLine("{0}", a.useMethod());   // prints 4
      }
    }
    

    同样的歧义也是以同样的方式解决的。但我想问的是这个案子在哪里

    • 方法 已定义,以及

    我们遇到

    qwerty = 4
    

    这是一个方法调用还是一个新的局部变量赋值?


    @迈克·斯通

    你好我理解并赞赏你提出的观点和你的建议 榜样是伟大的。相信我,如果我有足够的声誉, 我赞成你的回答。但我们仍然不同意:

    • 在语义问题上,以及
    • 以事实为中心

    首先,我要说的是,我们正在就 “歧义”的含义。

    当涉及到解析和编程语言语义时(主题 关于这个问题),你肯定会承认这个概念的广泛性 “歧义”。让我们采用一些随机符号:

    1. 歧义:语法歧义(yacc必须遵循解析树分析)
    2. 模棱两可:模棱两可,在执行时知道一切

    (2-3之间也有垃圾)。所有这些类别都由 说

    “qwerty=4”在C中是明确的#

    “qwerty=4”在ruby中没有歧义 (目前的情况)

    “qwerty=4”在C中是不明确的#

    我们还没有互相矛盾。最后,这里是我们真正需要的地方 不同意:如果没有进一步的改进,ruby可能实现,也可能无法实现 语言的结构是这样的,

    对于“qwerty=4”,ruby明确表示 如果存在,则调用现有的setter
    没有定义局部变量

    你说不,我说是;另一个ruby可能存在,其行为与 当前各方面,, 除了 “qwerty=4”定义了一个新的 存在,如果存在,则分配给本地。我完全接受我 可能是错的。事实上,我可能错的一个原因很有趣。

    让我解释一下。

    假设您正在编写一种具有访问器方法的新OO语言 比如实例vars(比如ruby&C#)。你可能会从 概念语法类似于:

      var = expr    // assignment
      method = expr // setter method invocation
    

    但是解析器编译器(甚至不是运行时)会呕吐,因为即使在 你面临着一个经典的选择。我不能确定细节,但是 ruby基本上做到了这一点:

      var = expr    // assignment (new or existing)
      // method = expr, disallow setter method invocation without .
    

    这就是为什么它是不含糊的,而C#做到了这一点:

      symbol = expr // push 'symbol=' onto parse tree and decide later
                    // if local variable is def'd somewhere in scope: assignment
                    // else if a setter is def'd in scope: invocation
    

    对于C#,'later'仍处于编译时。

    我相信ruby也可以这样做,但是“以后”必须在运行时,因为 正如ben指出的,在执行语句之前,您不知道是哪种情况 应用。

    我的问题从来不是要问“我真的需要‘自我’?”或“什么?” 我想知道为什么会这样 有什么特别的选择吗?也许这不是表演。也许它刚得到这份工作 完成,或者认为最好始终允许1-liner local覆盖

    但我想说的是,最有活力的语言可能是 延迟此决定的时间最长,并根据最上下文的上下文选择语义 信息:因此,如果您没有本地设置,并且您定义了一个setter,那么它将使用setter。不是吗 这就是为什么我们喜欢ruby、smalltalk和objc,因为方法调用是在运行时决定的, 提供最大的表现力?

    3 回复  |  直到 13 年前
    推荐文章