为什么Ruby setter需要;“自我”;课程内的资格?
Ruby setter无论是由为什么Ruby setter需要;“自我”;课程内的资格?,ruby,Ruby,Ruby setter无论是由(c)attr\u accessor创建的,还是手动创建的,似乎都是在类本身中访问时需要self.限定的唯一方法。这似乎让Ruby在语言世界中独占鳌头: 所有方法都需要self/this(比如Perl,我认为是Javascript) 没有方法需要self/这个是(C#,Java) 只有setter需要self/这个(Ruby?) 最好的比较是C与Ruby,因为这两种语言都支持语法上与类实例变量类似的访问器方法:foo.x=y,y=foo.x。C#称之为属性 这里
(c)attr\u accessor创建的,还是手动创建的,似乎都是在类本身中访问时需要self.
限定的唯一方法。这似乎让Ruby在语言世界中独占鳌头:
- 所有方法都需要
self
/this
(比如Perl,我认为是Javascript)
- 没有方法需要
self
/这个是(C#,Java)
- 只有setter需要
self
/这个
(Ruby?)
最好的比较是C与Ruby,因为这两种语言都支持语法上与类实例变量类似的访问器方法:foo.x=y
,y=foo.x
。C#称之为属性
这里有一个简单的例子;Ruby和C#中的相同程序:
去掉self.qwerty=()
,它就会失败(Linux和OS X上的Ruby 1.8.6)。现在C#:
问:这是真的吗?除了二传,还有其他需要自我的场合吗?也就是说,是否有其他情况下没有self就不能调用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
这是一个方法调用还是一个新的局部变量赋值
@迈克·斯通 嗨!我理解并赞赏你提出的观点和你的建议 榜样是伟大的。相信我,如果我有足够的声誉, 我赞成你的回答。但我们仍然不同意:
- 在语义问题上,以及
- 以事实为中心
没有定义局部变量 你说不,我说是;另一个ruby可能存在,其行为与 除“qwerty=4”外,各方面的电流定义了一个新的 变量当不存在setter和local时,如果存在setter,则调用setter 存在,如果存在,则分配给本地。我完全接受我 可能是错的。事实上,我可能错的一个原因很有趣 让我解释一下 假设您正在编写一种具有访问器方法的新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 .
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#做到了这一点:
var = expr // assignment (new or existing)
// method = expr, disallow setter method invocation without .
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,因为方法调用是在运行时决定的,
提供最大的表达能力?嗯,我认为这种情况的原因是因为
qwerty=4
不明确。您是定义一个名为qwerty
的新变量还是调用setter?Ruby通过说它将创建一个新变量来解决这个歧义,因此需要self.
这里是另一个需要自我的情况。
:
class A
def test
4
end
def use_variable
test = 5
test
end
def use_method
test = 5
self.test
end
end
a = A.new
a.use_variable # returns 5
a.use_method # returns 4
如您所见,对test
的访问不明确,因此需要self.
此外,这也是为什么C#示例实际上不是一个好的比较,因为您定义变量的方式与使用setter的方式不同。如果您在C#中定义了一个与访问器同名的变量,那么您需要用
这个限定对访问器的调用。
,就像Ruby案例一样。这里需要记住的重要一点是,Ruby方法可以在任何时候(取消)定义,以便智能地解决歧义,每个赋值
class ExampleClass
attr_reader :last_set
def method_missing(name, *args)
if name.to_s =~ /=$/
@last_set = args.first
else
super
end
end
def some_method
some_variable = 5 # Set a local variable? Or call method_missing?
puts some_variable
end
end
example = ExampleClass.new
example.blah = 'Some text'
example.last_set #=> "Some text"
example.some_method # prints "5"
example.last_set #=> "Some text"