只是好奇Rails gem中这两者之间的区别:
write_inheritable_attribute(:sample, "sample")
self.sample = "sample"
我在write_inheritable_attribute
上找不到任何好的文档,只是阅读了一些宝石源,发现前者使用了几次。谢谢!
答案 0 :(得分:13)
子类不继承实例变量:
>> class B ; @candy = 1 ; end
>> B.instance_variable_get :@candy # => 1
>> class C < B ; end
>> C.instance_variable_get :@candy # => nil
在rails中,可继承属性提供了一个解决方案:
>> class B ; end
>> B.write_inheritable_attribute(:candy, 7) # => 7
>> class C < B ; end
>> C.read_inheritable_attribute(:candy) # => 7
答案 1 :(得分:5)
对于一个简单的类或模块,没有区别,但是对于可以加载多个其他模块的更复杂的模块,像write_inheritable_attribute
这样的方法可以帮助您轻松可靠地修改对象,而无需担心范围,私人/受保护的方法以及像method_missing
这样的红宝石元编程魔法的各种干扰。
简而言之,当您编写foo.sample = "sample"
时,可能会在设置属性之前,之后或之后发生各种事情,尤其是在对象使用ActiveModel或ORM时。当您使用foo.write_inheritable_attribute(:sample, "sample")
时,您可以更好地控制发生的事情。
答案 2 :(得分:2)
实现了可继承属性主要是为了解决在类继承中共享ruby类变量的问题。考虑这个例子
class Counter
@@count = 0
def self.count
@@count
end
def self.increment
puts "==> #{self} increment"
@@count += 1
end
end
class DogCounter < Counter
end
puts "Counter.count: #{Counter.count}"
puts "DogCounter.count: #{DogCounter.count} -> nice, DogCounter inherits @@count from Counter"
DogCounter.increment
puts "DogCounter.count: #{DogCounter.count} -> as expected"
puts "Counter.count: #{Counter.count} -> but Counter.count is also changed!"
Counter.increment
puts "Counter.count: #{Counter.count}"
puts "DogCounter.count: #{DogCounter.count} -> @@count is shared with all the descendants of Counter"
这将产生此输出
Counter.count: 0
DogCounter.count: 0 -> nice, DogCounter inherits @@count from Counter
==> DogCounter increment
DogCounter.count: 1 -> as expected
Counter.count: 1 -> but Counter.count is also changed!
==> Counter increment
Counter.count: 2
DogCounter.count: 2 -> @@count is shared with all the descendants of Counter
请注意,因为Rails 3.2 write_inheritable_attribute已被删除。看到 http://dev.mensfeld.pl/2012/01/upgrading-to-rails-3-2-0-from-rails-3-1-3/
使用class属性(曾经是可继承属性)我们可以实现类似这样的东西:
class Counter
class_attribute :count
self.count = 0
def self.increment
puts "==> #{self} increment"
self.count += 1
end
end
class DogCounter < Counter
end
puts "Counter.count: #{Counter.count}"
puts "DogCounter.count: #{DogCounter.count} -> nice, DogCounter inherits count from Counter"
DogCounter.increment
puts "DogCounter.count: #{DogCounter.count} -> as expected"
puts "Counter.count: #{Counter.count} -> nice, it doesn't change count for Counter"
Counter.increment
puts "Counter.count: #{Counter.count}"
puts "DogCounter.count: #{DogCounter.count} -> now each subclass can have their own class attribute that inherits default value from the superclass"
这将产生此输出
Counter.count: 0
DogCounter.count: 0 -> nice, DogCounter inherits count from Counter
==> DogCounter increment
DogCounter.count: 1 -> as expected
Counter.count: 0 -> nice, it doesn't change count for Counter
==> Counter increment
Counter.count: 1
DogCounter.count: 1 -> now each subclass can have their own class attribute that inherits default value from the superclass