在David Flanagan的Ruby编程语言中; Yukihiro Matsumoto,他们声明变量前缀($,@,@@)是我们为能够省略方法调用的括号而支付的一个价格.谁可以给我解释一下这个?
这是我不成熟的看法。如果我错了,请纠正我。
假设实例变量没有前缀@,那么我们如何声明实例变量呢?
class MyClass
def initialize
# Here foo is an instance variable
self.foo = 'bar'
end
# Here foo is an instance method
def foo
end
def bar
# Call method. No doubt.
self.foo()
# Call method? Access instance variable?
self.foo
end
end
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,实例变量foo是使用假设语法初始化的
self.foo = 'bar'
Run Code Online (Sandbox Code Playgroud)
因为我们必须有办法告诉 ruby 解释器foo属于当前实例并且不是局部变量。
那么在方法中bar,如果方法调用时不强制使用括号,那么解释器如何判断是self.foo方法调用还是实例变量访问呢?
也许我们可以在缺少括号时让实例变量遮蔽实例方法,但这会导致语言本身的语法不一致。例如,从MyClass定义之外:
obj = MyClass.new
# Call instance method
obj.foo
Run Code Online (Sandbox Code Playgroud)
这是一个实例方法调用,因为所有实例变量从外部都是不可见的(至少在不使用元编程的情况下)。但self.foo方法中的(不带括号)bar是实例变量的访问。这种语法不一致可能会导致错误。此外,它还给解释器本身的实现带来了困难。
那么让实例方法影子实例变量怎么样?然后,程序员必须确保实例变量名称不会与实例方法名称冲突,否则实例变量将无法访问。如果一个类具有很长的祖先链,则非常困难,因为不仅必须检查当前类定义中的冲突,而且还必须检查其祖先中的冲突,这会破坏封装。
无论哪种方式,其代价都比为实例变量添加前缀要高得多。对于类变量和全局变量,情况类似。