JQ Blog

クラス変数、インスタンス変数、クラスインスタス変数

クラス変数

クラスに変数を持ちたい時にはクラス変数を定義すれば良い。@@というプレフィックスをつけるとクラス変数の定義して使うことができる。

1
2
3
4
5
6
7
8
9
10
11
class ParentVariable
  @@var = "Hello!"

  def class_var
    @@var
  end
end

class Variable < ParentVariable

end

クラス変数はサブクラスや通常のインスタンスメソッドからアクセスすることもできる。上記のVariableクラスのclass_varを実行してみると

1
2
3
4
irb> var = Variable.new
=> #<Variable:0x007f8483c8f730>
irb> var.class_var
=> "Hello!"

普通にクラス変数の@@varを取得できる。しかし、クラス変数には少し使いにくいところがある。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class ParentVariable
  @@var = "Hello!"

  def class_var
    @@var
  end
end

class Variable < ParentVariable
  @@var = "Good morning!"
end

irb> parent_var = ParentVariable.new
=> #<ParentVariable:0x007f8480e4dd90>
irb> prent_var.class_var
=> "Hello!"
irb> var = Variable.new
=> #<Variable:0x007f8480de7388>
irb> var.class_var
=> "Good morning!"
irb> pvar.class_var
=> "Good morning!"

こういうふうにクラス変数を変更する場合、このクラス変数にかかっている全てのオブジェクトに影響を与えるので実際の変数の値が変更されてしまう。ということで多くのRubyistはクラス変数は使ってない(らしい)。

インスタンス変数

インスタンス変数は@というプレフィックスをつけて使う。これはオブジェクトに所属していて、クラスとは何もつながりがない。なので、同じクラスのオブジェクトでもインスタンス変数の値はそれぞれ違う。インスタンス変数は値を代入した時に初めて出現する。だから明示的に定義しなくても良い。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Variable
  def instance_var var
    @var = "variable : '#{var}'."
  end
end

irb> var = Variable.new
=> #<Variable:0x007f8483923e98>
irb> var1 = var.instance_var "Hello"
=> "variable : 'Hello'."
irb> var2 = var.instance_var "Bye"
=> "variable : 'Bye'."
irb> var1
=> "variable : 'Hello'."
irb> var2
=> "variable : 'Bye'."

クラスインスタンス変数

Rubyでは、全てのインスタンス変数はカレントオブジェクトselfに属している。クラスの定義の中ではselfはクラスのことになるから、下記にクラスに定義された@varはクラスに属していることになる。同じインスタンス変数@varだけどどこに定義されているかによって違い、それぞれ異なるスコープに定義されており、別々のオブジェクトに属している。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Variable
  @var = "Class Instance Hello!"

  def initialize(str)
    @var = str
  end

  def instance_var
    @var
  end

  def self.class_instance_var
    @var
  end
end

irb> var = Variable.new "Instance Hello!"
=> #<Variable:0x007f8483c56bd8 @var="Instance Hello!">
irb> var.instance_var
=> "Instance Hello!"
irb> Variable.class_instance_var
=> "Class Instance Hello!"

1つ目instance_varメソッドで呼ばれた@varvarオブジェクトがselfになる。つまり、varオブジェクトのインスタンス変数だ。2つ目のclass_instance_varのクラス変数で呼ばれた@varVariableselfになる。つまり、これはVariableオブジェクトのインスタンス変数だ。これはClassクラスのオブジェクトであるVariableに属しているので通常のインスタンス変数だ。これをクラスインスタンス変数と呼ぶ。
クラスインスタンス変数はクラスからしかアクセスできない。クラスのインスタンスやサブクラスからはアクセスできない。

参照

メタプログラミングRuby 45p - インスタンス変数
メタプログラミングRuby 144 ~ 146p - クラスインスタンス変数