Ruby setters - 无论是由类创建(c)attr_accessor还是手动创建- 似乎是self.在类本身内访问时需要限定的唯一方法.这似乎使Ruby独自成为语言世界:
self/ this(像Perl,我认为是Javascript)self/ this是(C#,Java)self/ this(Ruby?)最好的比较是C#VS红宝石,因为这两种语言都支持这句法工作就像类的实例变量的访问方法: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
Run Code Online (Sandbox Code Playgroud)
带走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();
}
}
Run Code Online (Sandbox Code Playgroud)
问题:这是真的吗?除了需要自我的主持人之外还有其他场合吗?也就是说,在没有自我的情况下,有没有其他情况下无法调用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
}
}
Run Code Online (Sandbox Code Playgroud)
同样的歧义以同样的方式解决.但是,虽然微妙,我问的是案件在哪里
我们遇到了
qwerty = 4
Run Code Online (Sandbox Code Playgroud)
这是一个模糊的 - 这是一个方法调用还是一个新的局部变量赋值?
@Mike Stone
嗨!我理解并欣赏你所提出的观点,你的榜样很棒.相信我,当我说,如果我有足够的声誉,我会投票你的回应.但我们仍然不同意:
首先,我声称,不是没有讽刺意味,我们正在就"歧义"的含义进行语义辩论.
当谈到解析和编程语言语义(这个问题的主题)时,你肯定会承认广泛的概念"歧义".我们只是采用一些随机表示法:
(也有2-3之间的垃圾).所有这些类别都通过收集更多的上下文信息来解决,在全球范围内越来越多.所以,当你说,
当没有定义变量时,"qwerty = 4"在C#中是UNAMBIGUOUS ...
我完全同意.但出于同样的原因,我说
红宝石中的"qwerty = 4"是不明确的(因为它现在存在)
"qwerty = 4"在C#中是不明确的
而且我们还没有相互矛盾.最后,这里是我们真正不同意的地方:如果没有任何进一步的语言结构,可以或不可能实现ruby,
对于"qwerty = 4",如果
没有定义局部变量,ruby UNAMBIGUOUSLY将调用现有的setter
你说不.我说是; 另一个ruby可能存在,其行为与每个方面的当前行为完全相同,除了 "qwerty = 4"定义了一个新变量,当没有setter且没有local存在时,它调用setter(如果存在),并且如果存在则分配给本地.我完全接受我可能是错的.事实上,我可能错的原因很有趣.
让我解释.
想象一下,你正在编写一个新的OO语言,其访问器方法看起来像实例变量(如ruby和C#).您可能从概念语法开始,例如:
var = expr // assignment
method = expr // setter method invocation
Run Code Online (Sandbox Code Playgroud)
但是解析器编译器(甚至不是运行时)都会呕吐,因为即使在所有输入都被删除之后,也无法知道哪个语法是相关的.你面临着一个经典的选择.我不能确定细节,但基本上ruby这样做:
var = expr // assignment (new or existing)
// method = expr, disallow setter method invocation without .
Run Code Online (Sandbox Code Playgroud)
这就是为什么它不明确,而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
Run Code Online (Sandbox Code Playgroud)
对于C#,'later'仍处于编译时.
我确信ruby也可以这样做,但是'later'必须在运行时,因为ben指出你不知道,直到语句执行哪种情况适用.
我的问题从来没有打算表示"我真的需要'自我'吗?" 或"正避免什么潜在的歧义?" 相反,我想知道为什么这个特别的选择?也许这不是表现.也许它只是完成了工作,或者最好总是允许1-liner本地覆盖方法(一种非常罕见的情况要求)......
但我有点建议最动态的语言可能是推迟这个决定最长的语言,并根据最大的上下文信息选择语义:所以如果你没有本地并且你定义了一个setter,它会使用setter .这不是我们喜欢ruby,smalltalk,objc的原因,因为方法调用是在运行时决定的,提供最大的表现力吗?
Mik*_*one 83
好吧,我认为这种情况的原因是因为qwerty = 4模糊不清 - 您是否定义了一个名为qwerty或调用setter 的新变量?Ruby通过说它将创建一个新变量来解决这种歧义,因此这self.是必需的.
这是您需要的另一个案例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
Run Code Online (Sandbox Code Playgroud)
如您所见,访问权限test不明确,因此self.需要.
此外,这就是为什么C#示例实际上不是一个很好的比较,因为您以一种明确的方式定义变量,使用setter.如果您在C#中定义了一个与访问者名称相同的变量,则需要使用this.Ruby案例限定对访问者的调用.
ben*_*ben 18
这里要记住的重要事情是Ruby方法可以在任何时候(un)定义,因此为了智能地解决歧义,每个赋值都需要运行代码来检查当时是否存在具有赋值名称的方法任务.
Aje*_*i32 17
因为否则就不可能在方法中设置局部变量.variable = some_value很暧昧.例如:
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
Run Code Online (Sandbox Code Playgroud)
如果self不是生成器,some_method则会提高NameError: undefined local variable or method 'some_variable'.但是,该方法按预期工作:
example = ExampleClass.new
example.blah = 'Some text'
example.last_set #=> "Some text"
example.some_method # prints "5"
example.last_set #=> "Some text"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9384 次 |
| 最近记录: |