Ruby setter(无论是由(c)attr_accessor
创建的还是手动创建的)似乎是在类自身内部进行访问时唯一需要self.
限定的方法。这似乎把红宝石单独的语言世界:为什么Ruby制定者需要“自我”。在课堂上的资格?
- 所有方法都需要
self
/this
(如Perl,我认为JavaScript)的 - 没有方法需要
self
/this
是(C#,Java的) - 只有制定者需要
self
/this
(红宝石?)
最好的比较是C#VS红宝石,因为这两种语言都支持这句法工作就像类斯塔存取方法nce变量:foo.x = y
,y = foo.x
。 C#调用它们的属性。
下面是一个简单的例子;在红宝石同一程序然后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 =()
和失败(红宝石1.8.6在Linux & OS X)。现在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
这是模棱两可的 - 这是一个方法调用还是一个新的局部变量赋值?
@Mike石
嗨!我理解并欣赏您提出的观点,并且您的示例很棒。相信我,当我说,如果我有足够的声誉, 我会投你的回应。然而,我们仍然不同意:
- 语义上的问题,并在事实上
首先我要求,不无讽刺,我们具有关于语义争论的中心点
当谈到解析和编程语言语义(这个问题的主题 ),当然你会承认广泛的概念 '歧义'。让我们只采用一些随机的符号:
- 暧昧:词汇歧义(法必须“向前看”)
- 暧昧:歧义(YACC必须按照解析树分析)
- 含糊:歧义知道一切在执行的时刻
(并且在2-3之间也有垃圾)。所有这些类别均由 解决,收集更多上下文信息,在全球范围内看起来越来越多。所以,当你 说,
“QWERTY = 4” 是在C# 明确的时候没有定义的变量...
我不能同意。但是,同样的道理,我说
“QWERTY = 4” 是红宝石 未明确(因为它现在已经存在)
“QWERTY = 4” 是在C#不明确
而且我们还没有相互矛盾。最后,这就是我们真正 不同意:无论是红宝石可以或不可以在没有任何进一步的 语言结构实现,这样,
对于“QWERTY = 4,”红宝石明确 调用现有的二传手,如果有
是没有定义的局部变量
你说不。我说是;另一个红宝石可能存在,其行为与 完全相同,除外“qwerty = 4”定义了一个新的 变量,当没有setter和本地存在时,它调用setter,如果一个 存在,并且它分配给本地(如果存在)。我完全同意我可能是错误的 。事实上,我可能会犯错的原因很有意思。
让我解释一下。
想象一下,您正在编写一个新的面向对象方法,使用像实例变量(如ruby & C#)的 。你可能有 概念语法像开始:
var = expr // assignment
method = expr // setter method invocation
但是解析器编译器(甚至不运行时)会吐的,因为即使在 所有的输入grokked有没有办法知道哪些语法相关。 您正面临着哪一个经典选择。我不能肯定的细节,但 基本上红宝石做到这一点:
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#,“以后'仍在编译时。
我敢肯定,红宝石可以做同样的事情,但'稍后'必须在运行时,因为 明确指出,你不知道,直到执行声明 适用。
我的问题从来没有打算表示“我真的需要'自我'吗?”?或“什么 潜在的歧义正在被避免?”相反,我想知道为什么这个 做出了特别的选择?也许这不是性能。也许它只是完成了 的工作,或者它被认为是最好的总是允许1班轮本地覆盖 方法(一个非常罕见的情况下要求)...
但我有点暗示,最动态的语言可能是 推迟这个决定的时间最长的语言,并且选择基于最上下文 信息的语义:所以如果你没有本地并且你定义了一个setter,它会使用setter。这不是 这就是为什么我们喜欢ruby,smalltalk,objc,因为方法调用在运行时决定, 提供最大的表现力?
PHP在访问实例变量时也需要`$ this->`。这让我一直在旅行。 – Chloe 2014-01-01 23:50:55
只有类方法需要显式接收器,而不是实例方法。 – 2014-10-01 23:52:17
我同意 - 我也不喜欢这种解决amibuity的方法。违反最少惊喜的原则。 – Dogweather 2016-01-17 22:14:18