2011-12-03 16 views
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'を入れるにはどうしたらいいですか?継承クラスのRubyとクラス変数

+0

インスタンス変数が必要なのは確かですか? (例:@vの代わりに@v) – cvshepherd

答えて

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 

それを理解するには、およそAClassクラスのインスタンスとしてを考えなければならない(とそれはそれはRubyでいる方法です)。 fooだけAクラスのすべてのインスタンスのためのaオブジェクトとないために定義された方法であり、その場合には

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

:しかし、Rubyではすべてのオブジェクトは、オブジェクト自体に定義されたメソッドのようなオブジェクト固有のものを格納し、独自のシングルトンクラスを持っています。 (それは少しトリッキーだ我々はAクラスのシングルトンクラスのコンテキストでclass_var属性アクセサを定義するためにこのアプローチを使用して最初のコードスニペットで

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変数とその子孫クラスBを持ちます。違いは、それらのすべてが干渉しない独自の変数class_varを持っていることです。

+0

ありがとうございます。素晴らしい答えです。 – Ximik

-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がののクラス変数のクラスのすべてのインスタンスに対して同じ値を持つため、2番目のオブジェクトの@@ vの値は、以外の場合はです。

+1

実際の問題は、Rubyのクラス変数が実際にクラス階層の変数であることです。クラスはクラス変数をすべての子孫と共有します。 –

2

もう1つの選択肢は、Railsからclass_inheritable_accessor codeを取り出し、その動作をクラスに含めることです。良い議論とコードの勇気については、hereを参照してください。

おそらく、実際にはクラス変数は必要ありません。

+0

リンクをご利用いただき、ありがとうございます。私はそれを読むでしょう。 – Ximik

+1

@Ximik問題ありません。これは、基本的に、KL-7の答えの拡張可能で階層的なバージョンです。 –