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のみメソッドが定義されます。オブジェクトのシングルトン クラスでメソッドを定義する別の方法は次のとおりです。aA

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

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

于 2011-12-03T16:35:43.877 に答える