可继承属性的实现主要是为了解决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_属性就被删除了。见
http://dev.mensfeld.pl/2012/01/upgrading-to-rails-3-2-0-from-rails-3-1-3/
使用类属性(以前是可继承属性)我们可以实现如下内容:
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