web-dev-qa-db-ja.com

クラス変数とクラスインスタンス変数の違いは?

クラス変数とクラスインスタンス変数の違いについて教えてもらえますか?

89
cmd

クラス変数(@@)は、クラスとそのすべての子孫の間で共有されます。クラスインスタンス変数(@)は、クラスの子孫によって共有されません。


クラス変数(@@

クラス変数@@iを持つクラスFooと、@@iを読み書きするためのアクセサを用意しましょう。

class Foo

  @@i = 1

  def self.i
    @@i
  end

  def self.i=(value)
    @@i = value
  end

end

そして、派生クラス:

class Bar < Foo
end

FooとBarの@@iの値は同じであることがわかります。

p Foo.i    # => 1
p Bar.i    # => 1

@@iを1つ変更すると、両方で変更されます:

Bar.i = 2
p Foo.i    # => 2
p Bar.i    # => 2

クラスインスタンス変数(@

クラスインスタンス変数@iと、@iを読み書きするためのアクセサを使用して、簡単なクラスを作成しましょう。

class Foo

  @i = 1

  def self.i
    @i
  end

  def self.i=(value)
    @i = value
  end

end

そして、派生クラス:

class Bar < Foo
end

Barは@iのアクセサを継承しますが、@i自体は継承しません。

p Foo.i    # => 1
p Bar.i    # => nil

Fooの@iに影響を与えることなく、Barの@iを設定できます。

Bar.i = 2
p Foo.i    # => 1
p Bar.i    # => 2
149
Wayne Conrad

最初に、クラスもインスタンスであることを理解する必要があります。Classクラスのインスタンスです。

それを理解すれば、通常の(読み取り:非クラス)オブジェクトと同様に、クラスにインスタンス変数を関連付けることができることを理解できます。

Hello = Class.new

# setting an instance variable on the Hello class
Hello.instance_variable_set(:@var, "good morning!")

# getting an instance variable on the Hello class
Hello.instance_variable_get(:@var) #=> "good morning!"

Helloのインスタンス変数は、instance of Helloのインスタンス変数とはまったく関係がなく、区別されていることに注意してください。

hello = Hello.new

# setting an instance variable on an instance of Hello
hello.instance_variable_set(:@var, :"bad evening!")

# getting an instance variable on an instance of Hello
hello.instance_variable_get(:@var) #=> "bad evening!")

# see that it's distinct from @var on Hello
Hello.instance_variable_get(:@var) #=> "good morning!"

一方、クラス変数は、Hello自体とそのインスタンス、およびHelloのサブクラスと、それらのインスタンス:

HelloChild = Class.new(Hello)
Hello.class_variable_set(:@@class_var, "strange day!")
hello = Hello.new
hello_child = HelloChild.new

Hello.class_variable_get(:@@class_var) #=> "strange day!"
HelloChild.class_variable_get(:@@class_var) #=> "strange day!"
hello.singleton_class.class_variable_get(:@@class_var) #=> "strange day!"
hello_child.singleton_class.class_variable_get(:@@class_Var) #=> "strange day!"

上記の奇妙な振る舞いのため、多くの人がclass variablesを避け、代わりにclass instance variablesの使用を推奨すると言います。

70
horseyguy

また、クラス変数(@@)クラスの任意のインスタンスから

class Foo
  def set_name
    @@name = 'Nik'
  end

  def get_name
    @@name
  end
end


a = Foo.new
a.set_name
p a.get_name # => Nik
b = Foo.new
p b.get_name # => Nik

ただし、クラスインスタンス変数(@

class Foo
  def set_name
    @name = 'Nik'
  end

  def get_name
    @name
  end
end


a = Foo.new
a.set_name
p a.get_name # => Nik
b = Foo.new
p b.get_name # => nil
0
Evan Ross