前几天我注意到Ruby中的实例变量有一些奇怪的行为。我试图添加一个实例变量数组,包含该类的其他实例变量“属性”。该类初始化时没有任何参数,但我仍然想在初始化时创建这个数组。这是一个(精简的)类的例子:
class Foo
attr_accessor :bar, :baz
attr_reader :attrs
def initialize
@attrs = [@bar, @baz]
end
end
这就是奇怪的地方:
f = Foo.new #=><Foo.0x[object_id] @attrs=[nil, nil]>
f.bar = "bar" #=>"bar"
f.baz = "baz" #=>"baz"
f.attrs #=>[nil, nil]
初始化时,我可以看到Foo.attrs
是[nil, nil]
。但在更新Foo.bar
和Foo.baz
后,为什么Foo.attrs
仍在返回[nil, nil]
?为什么他们的新价值没有反映出来?
我认为这不是最好的方法,并找到了解决方法,但我仍然对这种行为感到好奇。
答案 0 :(得分:2)
因为这就是变量的工作方式,这里和几乎所有其他编程语言都是如此。
您的数组在创建数组时包含@bar
和@baz
的值。 不包含对变量本身的引用。修改一个不会修改另一个。
有效地你已经完成了这个:
x = 3;
y = x;
x = 4;
# Why doesn't y equal 4?
y
不是4
,因为x
和y
共享值,但不相关。将x
重新分配给新值不会修改y
包含的值。
如果您希望这个工作,您需要使用成员变量的当前值创建一个按需构建数组的访问器:
class Foo
attr_accessor :bar, :baz
def attrs
[@bar, @baz]
end
end
答案 1 :(得分:0)
您只需添加puts
并查看会发生什么
class Foo
attr_accessor :bar, :baz
attr_reader :attrs
def initialize
@attrs = [@bar, @baz]
puts "inside initialize"
end
end
现在,您可以在创建Foo
f = Foo.new
#=> inside initialize
#=> #<Foo:0x2bc1bb0 @attrs=[nil, nil]>
f.bar = "bar" #=>"bar" , "inside initialize" not printed
如果您确实要分配它们,请创建一个setter
class Foo
attr_accessor :bar, :baz
attr_reader :attrs
def initialize
@attrs = [@bar, @baz]
puts "inside initialize"
end
def bar=(v)
@bar = v
@attrs = [@bar,@baz]
end
def baz=(v)
@baz = v
@attrs = [@bar,@baz]
end
end
f = Foo.new
#=> inside initialize
#=> #<Foo:0x2bc1bb0 @attrs=[nil, nil]>
f.bar = "bar"
f.attrs #=> ["bar", nil]
f.baz = "baz"
f.attrs #=> ["bar", "baz"]