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.new.put 中有'b'?
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.new.put 中有'b'?
这是一篇关于主题的好文章 - 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
类实例定义。在对象的单例类中定义方法的另一种方法是:
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
变量,不会干扰。
另一种选择是从 Rails 中提取class_inheritable_accessor
代码并将其行为包含在您的类中。请参阅此处以获得良好的讨论和代码的内容。
不过,也许您并不真正想要一个类变量。
为类变量(@@ 变量)赋值会为类的每个实例设置它。它甚至为“尚未创建”的实例“设置”它。所以,考虑这个...
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 是一个类变量这一事实,因此它对于类的每个实例都具有相同的值。