Ruby:实例变量与局部变量

Mat*_*tty 10 ruby

我现在正在学习Ruby,我很困惑为什么我可以在不使用@sigil的情况下引用实例变量,这也会使它成为局部变量.当然,以下代码不应该像以下一样工作:

class Test
  attr_accessor :variable
  def something
    variable
  end
  def something2
    @variable
  end
  def something3
    self.variable
  end
end

y = Test.new
y.variable = 10
puts y.something  # => 10
puts y.something2 # => 10
puts y.something3 # => 10
Run Code Online (Sandbox Code Playgroud)

我原本预计y.something会返回零.为什么局部变量和实例变量指向同一位置?我会预期@variablevariable已经过两次离散变量.

mol*_*olf 19

在您发布的代码,variable不是一个局部变量.它是对名为的实例方法的方法调用variable,它由以下定义:

attr_accessor :variable
Run Code Online (Sandbox Code Playgroud)

这是以下方法定义的简写:

def variable
  @variable
end

def variable=(value)
  @variable = value
end
Run Code Online (Sandbox Code Playgroud)

请注意,Ruby不需要括号()用于方法调用,因此区分局部变量和方法并不总是那么容易.

比较您的代码:

class Test
  attr_accessor :foo

  def example1
    foo = nil  # 'foo' is now a local variable
    foo
  end

  def example2
    foo        # 'foo' is a method call
  end
end

x = Test.new
x.foo = 10
x.example1  # => nil
x.example2  # => 10
Run Code Online (Sandbox Code Playgroud)

  • @bheeshmar:不,`foo = nil`永远不会调用方法.你必须使用`self.foo = nil`来实现这一目标. (6认同)
  • Nitpick:完全可以在不知道存在哪些方法的情况下区分局部变量引用和无参数无接收器消息.实际上,它*可能*,因为区分是在分析时静态进行的,而方法是在运行时动态定义的.IOW:当区分时,方法甚至还不存在.将`foo = nil`替换为`if false; foo = 42 end`看看它究竟是如何工作的. (2认同)