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
違いは、それらのすべてが干渉しない独自の変数を持っていることです。
もう 1 つのオプションは、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 はどのように値を持つことができますか? 2 番目のオブジェクトの @@v の値は、@@ v がクラス変数であるという事実を除いて設定されないため、クラスのすべてのインスタンスで同じ値になります。