class A
def set(v)
@@v = v
end
def put
puts @@v
end
end
class B < A
end
class C < A
end
B.new.set 'b'
B.new.put # => b
C.new.set 'c'
C.new.put # => c
B.new.put # => c
为什么呢?我应该怎么写这个'b'在最后B.new.put?
答案 0 :(得分:5)
这是一篇关于这个主题的好文章 - Class and Instance Variables In Ruby。
基本上,你可以做的是:
class A
class << self
attr_accessor :class_var
end
def set_class_var(value)
self.class.class_var = value
end
def get_class_var
self.class.class_var
end
end
class B < A; end
A.class_var = 'a'
B.class_var = 'b'
puts A.class_var # => a
puts B.class_var # => b
A.new.set_class_var 'aa'
B.new.set_class_var 'bb'
puts A.new.get_class_var # => aa
puts B.new.get_class_var # => bb
要理解它,您应该将A
视为Class
类的实例(这就是Ruby中的实例)。但是Ruby中的每个对象都有自己的单例类,它存储特定于对象的东西,比如在对象本身上定义的方法:
a = A.new
def a.foo
puts 'foo'
end
在这种情况下,foo
是仅为a
对象定义的方法,而不是为A
类的每个实例定义的方法。另一种在object的singleton类中定义方法的方法就是:
class << a # open a's singleton class
def bar # define method that will be available only on 'a' object
puts 'bar'
end
end
在第一个代码片段中,我们使用该方法在我们的class_var
类的单例类的上下文中定义A
属性访问器(这有点棘手,所以你需要考虑它)。由于结果类本身具有class_var
变量及其后代类B
。不同之处在于,每个人都有自己的class_var
变量,不会干扰。
答案 1 :(得分:2)
另一种选择是从Rails中提取class_inheritable_accessor
code并将其行为包含在您的类中。请参阅here以获得良好的讨论和代码的内容。
但也许你真的不想要一个类变量。
答案 2 :(得分:-1)
为类变量(@@变量)赋值为每个类的实例设置它。它甚至为“尚未创建”的实例“设置”它。所以,考虑一下......
B.new.set 'b' # OK, that set @@v for that particular instance of B
B.new.put # Hey, you just created *another* new instance of B!
@@ v如何在该值中有价值?第二个对象的@@ v值将被取消,除之外,因为@@ v是类变量,所以它与的值相同类的实例。