继承类中的Ruby和类变量

时间:2011-12-03 16:23:40

标签: ruby class-variables

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?

3 个答案:

答案 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是类变量,所以它与的值相同类的实例。