3

我有一个代码:

class A
  attr_accessor :somevar

  def a
    somevar = 'something'
    puts @somevar
  end

  def b
    send :somevar=, 'something'
    puts @somevar
  end

end

A.new.a #=> nil
A.new.b #=> 'something'

为什么有区别?为什么我不能通过编写器分配一个实例变量?但是为什么创建了局部变量而不是调用了方法(setter)?

4

2 回答 2

7

attr_accessor :somevar引用实例变量@somevar。实例变量必须以@符号开头。所有其他变量,如方法中没有符号的“somevar”,@只是该方法或范围的局部变量,而不是对象的实例变量。

因此,将方法“a”中的第一行更改为

@somevar = 'something'

会得到你期望的答案。

相关说明:您不必在 Ruby 中声明实例变量,只需使用@somevar类型表示法创建它们。该attr_accessor方法为该实例变量创建 setter 和 getter。

Ruby 中的方法附加到对象,因此为了让类 A 调用它自己的 somevar setter 方法,您需要编写self.somevar = 'something',否则 Ruby 解析器认为您只是在创建一个局部变量。

这可能会令人困惑,因为您可以调用afrom的方法b,只需执行以下操作:

def b
  send :somevar=,'something'
  puts @somevar
  a  # would invoke its own method 'a'
end

但是 setter 方法somevar=在创建具有相同符号的局部变量时是模棱两可的:

somevar='something'  # Ruby assumes you want to create a local variable

因此,要调用 somevar setter 方法,您需要明确说明您正在调用 self 上的方法:

self.somevar = 'something'

当你打电话时,send :somevar=,'something'你也在调用 somevar 实例方法。

于 2012-06-06T11:51:01.650 回答
1

这是因为方法 a 正在创建一个名为 somevar 的局部变量。这只是 Ruby 的小怪癖之一。您可以通过执行self.somevar = 'something'或来解决此问题@somevar = 'something'

于 2012-06-06T11:47:20.793 回答