Ruby and class variables in inherit class

为君一笑 提交于 2019-12-24 03:07:07

问题


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

Why? And how should I write this to have 'b' in last B.new.put?


回答1:


Here is a nice article on the subject - Class and Instance Variables In Ruby.

Basically, what you can do is:

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

To understand it you should think about A as an instance of Class class (and that's how it is in Ruby). But every object in Ruby has its own singleton class that stores object-specific stuff like methods defined on object itself:

a = A.new
def a.foo
  puts 'foo'
end

In that case foo is method defined only for a object and not for every instance of A class. And another way to define method in object's singleton class is like that:

class << a # open a's singleton class
  def bar  # define method that will be available only on 'a' object
    puts 'bar'
  end
end

In the first code snippet we use that approach to define class_var attribute accessor in the context of singleton class of our A class (it's a bit tricky, so you need to think about it). As the result class itself has class_var variable as well as its descendant class B. The difference is that every one of them has its own class_var variable that do not interfere.




回答2:


Another option is to pull out class_inheritable_accessor code from Rails and include its behavior in your classes. See here for a good discussion and the guts of the code.

Perhaps you don't really want a class variable, though.




回答3:


Assigning a value to a class variable (an @@ variable) sets it for EVERY instance of the class. It even "sets" it for instances that "aren't created yet." So, consider this...

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!  

How can @@v have a value in that one? The second object's value of @@v would be unset, except for the fact that @@v is a class variable, so it has the same value for every instance of the class.



来源:https://stackoverflow.com/questions/8369050/ruby-and-class-variables-in-inherit-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!