Ruby setter无论是由(c)attr_accessor创建的还是手动创建的,似乎是在类本身中访问时唯一需要self.限定的方法.这似乎让Ruby在语言世界中独占鳌头:

  • 所有方法都需要self/this(比如Perl,我认为Javascript)
  • 没有方法需要self/this is(C#,Java)
  • 只有二传手需要self/this(Ruby ?)

最好的比较是C#和Ruby,因为这两种语言都支持访问器方法,它们在语法上就像类实例变量:foo.x = yy = 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();
  }
}

问题:这是真的吗?除了二传,还有其他需要self 的场合吗?也就是说,在其他情况下是否会调用Ruby方法cannot

当然,在很多情况下,self 保护是必要的.这并不是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
  }
}

同样的歧义也会以同样的方式解决.但我想问的是这个案子

  • 已定义方法has,以及
  • 已定义No个局部变量,并且

我们遇到

qwerty = 4

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


@迈克·斯通

你好我理解并感谢你所提出的观点和你的建议

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

首先,我要说的是,我们正在就

当涉及到语法分析和编程语言语义(主题

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

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

"qwerty=4"在C中是明确的#

我完全同意.但出于同样的原因,我要说

"qwerty=4"在ruby中没有歧义

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

我们还没有相互矛盾.最后,这里是我们真正的

对于"qwerty=4",ruby明确表示

你说不,我说是;另一个ruby可能存在,其行为与

让我解释一下.

想象一下,您正在编写一种带有访问器方法的新OO语言

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

但是解析器编译器(甚至不是运行时)会呕吐,因为即使在

  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也可以这样做,但是"以后"必须在运行时,因为

我的问题从来不是想说"我真的需要‘self ’?"或者"什么

但我想说的是,最有活力的语言可能就是

推荐答案

这里需要记住的重要一点是,Ruby方法可以在任何时候(取消)定义,因此为了智能地解决歧义,每个赋值都需要运行代码,以判断在赋值时是否有一个方法具有指定给的名称.

Ruby相关问答推荐

Ruby类构造函数使用`()`而不是`. new()`

如何在 Ruby 中反转数字的字节顺序

当 node 名称是/包含整数时,使用 Nokogiri 解析非 XML 文档

多线程期间的 MRI ruby​​ 内存访问特性

在 Ruby 中使用委托维护相同的类

设计登录根路由rails 3

判断一个数组是否是Ruby中另一个数组的子集

Jekyll 默认安装没有 _layouts 目录

当没有传入块时,是否有更好的方法来防止屈服?

在 YAML 变量中包含 jekyll / liquid 模板数据?

Ruby - 查看端口是否打开

object_id 分配如何工作?

在 Ruby 中,有没有办法使用 hash.each_with_index do |[k,v], i| 之类的东西?

对于基于 GitHub 的 gem,强制Bundle 安装使用 https:// 而不是 git://

. vs ::(点与双冒号)用于调用方法

带有可选参数的方法

如何将多个元素添加到数组中?

使用 RSpec 测试哈希内容

如何在 Ruby 中使用全局变量或常量值?

在 Ruby 中解析制表符分隔文件的最佳方法是什么?