Aet*_*rus 1

这是我不成熟的看法。如果我错了,请纠正我。

假设实例变量没有前缀@,那么我们如何声明实例变量呢?

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是实例变量的访问。这种语法不一致可能会导致错误。此外,它还给解释器本身的实现带来了困难。

那么让实例方法影子实例变量怎么样?然后,程序员必须确保实例变量名称不会与实例方法名称冲突,否则实例变量将无法访问。如果一个类具有很长的祖先链,则非常困难,因为不仅必须检查当前类定义中的冲突,而且还必须检查其祖先中的冲突,这会破坏封装。

无论哪种方式,其代价都比为实例变量添加前缀要高得多。对于类变量和全局变量,情况类似。