Ruby setter——无论是由 (c)attr_accessor
创建的或手动——似乎是唯一需要的方法 self.
在类本身中访问时的限定。这似乎让 Ruby 在语言世界中独树一帜:
self
/this
(像 Perl,我认为是 Javascript)self
/this
是(C#,Java)self
/this
( ruby ?)最好的比较是 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();
}
}
问题:这是真的吗?除了需要 self 的 setter 之外,还有其他场合吗?即,是否还有其他场合无法在没有 self 的情况下调用 Ruby 方法?
肯定有很多情况需要 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
}
}
同样的歧义以同样的方式解决。但是虽然微妙,但我问的是这种情况
我们遇到
qwerty = 4
这是模棱两可的——这是一个方法调用还是一个新的局部变量赋值?
@迈克·斯通
嗨!我理解并感谢你提出的观点和你的
例子很棒。相信我,如果我有足够的声誉,
我会投票赞成你的回应。然而我们仍然不同意:
首先我声称,并非没有讽刺意味,我们正在进行一场关于
“歧义”的意思。
当涉及到解析和编程语言语义(主题
这个问题),你肯定会承认这个概念的广泛性
'歧义'。让我们采用一些随机符号:
(而且 2-3 之间也有垃圾)。所有这些类别都由
收集更多上下文信息,越来越全局化。所以当你
说,
"qwerty = 4" is UNAMBIGUOUS in C# when there is no variable defined...
我完全同意。但出于同样的原因,我是说
"qwerty = 4" is un-Ambiguous in ruby (as it now exists)
"qwerty = 4" is Ambiguous in C#
而且我们还没有相互矛盾。最后,这是我们真正的地方
不同意: ruby 可以或不能在没有任何进一步的情况下实现
语言构造使得,
For "qwerty = 4," ruby UNAMBIGUOUSLY invokes an existing setter if there
is no local variable defined
你说不。我说是;另一个 ruby 可能存在,其行为与
各方面的电流,除了“qwerty = 4”定义了一个新的
当没有 setter 和 local 存在时变量,如果有,则调用 setter
存在,如果存在,则分配给本地。我完全接受我
可能是错的。事实上,我可能错的原因会很有趣。
让我解释。
想象一下,您正在编写一种新的 OO 语言,其中的访问器方法看起来像
像实例变量(像 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#,“稍后”仍处于编译时。
我确信 ruby 可以做同样的事情,但“稍后”必须在运行时,因为
正如本指出的那样,在执行语句之前您不知道哪种情况
适用。
我的问题从来就不是“我真的需要‘自我’吗?”或者是什么
正在避免潜在的歧义?”相反,我想知道这是为什么
做了什么特别的选择?也许这不是性能。也许它只是得到了这份工作
完成,或者被认为最好总是允许 1-liner local 覆盖
方法(一种非常罕见的情况要求)...
但我有点建议最有活力的语言可能是那种
将这个决定推迟最久,并根据最上下文选择语义
信息:所以如果你没有本地并且你定义了一个setter,它会使用setter。是不是
这就是为什么我们喜欢 ruby、smalltalk、objc,因为方法调用是在运行时决定的,
提供最大的表现力?
最佳答案
这里要记住的重要一点是,Ruby 方法可以在任何时候(取消)定义,因此为了智能地解决歧义,每个赋值都需要运行代码来检查当时是否存在具有赋值名称的方法的任务。
关于ruby - 为什么 Ruby setter 需要 "self."类内的资格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44715/