2
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'?

4

3 回答 3

5

这是一篇关于主题的好文章 - 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变量,不会干扰。

于 2011-12-03T16:34:31.023 回答
2

另一种选择是从 Rails 中提取class_inheritable_accessor代码并将其行为包含在您的类中。请参阅此处以获得良好的讨论和代码的内容。

不过,也许您并不真正想要一个类变量。

于 2011-12-03T16:52:34.507 回答
-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 是一个类变量这一事实,因此它对于类的每个实例都具有相同的值。

于 2011-12-03T16:35:43.877 回答