クラス変数とインスタンス変数と時々クラスインスタンス変数

FJORD BOOT CAMPの課題の中で、クラスインスタンス変数を使用したので各変数の特徴?を簡潔にまとめてみた。

インスタンス変数

特徴

  1. インスタンス変数にアクセスできるのは、initializeメソッド、オブジェクトのインスタンスメソッドのみ
  2. インスタンス毎に独立しているため、異なるインスタンス間で変数の値は共有されない

@で始まる変数はインスタンス変数であり、特定のオブジェクトに所属しています。インスタンス変数はそのクラスまたはサブクラスのメソッドから参照できます。初期化されていないインスタンス変数を参照した時の値はnilです。

# インスタンス変数
class Capital
  def initialize
    # capital_nameがインスタンス変数となる
    @capital_name = 'Tokyo'
  end
  def capital_name
    @capital_name
  end
end
# インスタンスの初期化
yamada = Capital.new
p yamada.capital_name
#=> "Tokyo"

下記の時、yamadasuzukiインスタンスが使用する@capital_nameの値は共通ではなく、インスタンス毎にインスタンス変数の値は保持される

class Capital
  def initialize
    @capital_name = 'Tokyo'
  end
  def capital_name
    @capital_name
  end
  def change_capital_name(new_capital)
     @capital_name = new_capital
  end
end

yamada = Capital.new
yamada.change_capital_name('Saitama')
suzuki = Capital.new
# 同じ@capital_nameを参照しているがインスタンスが異なるため値は共有されていない
p yamada.capital_name
#=> "Saitama"
p suzuki.capital_name
#=> "Tokyo

クラス変数

特徴

  1. クラスとそのインスタンスがスコープになる
  2. クラス変数は異なるインスタンス間でも値が共有される
  3. クラスメソッド、インスタンスメソッド、クラス定義式内でアクセス可能

@@で始まる変数はクラス変数です。クラス変数はクラス定義の中で定義され、クラスの特異メソッド、インスタンスメソッドなどから参照/代入ができます。 クラス変数と定数の違いは以下の通りです。
・再代入可能(定数は警告を出す)
・クラスの外から直接参照できない(継承されたクラスからは参照/代入可能)

class Capital
  @@capital_name = 'Tokyo'
  def capital_name
    @@capital_name
  end
  def change_capital_name(new_capital)
     @@capital_name = new_capital
  end
end
# 同じ@capital_nameを参照しインスタンスが異なるが値は共有されている
yamada = Capital.new
yamada.change_capital_name('Saitama')
suzuki = Capital.new
p yamada.capital_name
#=> "Saitama"
p suzuki.capital_name
#=> "Saitama"
p Capital.capital_name
#=> これは参照できない!
# 関数の前にselfをつけると、クラスを直接参照することができる
class Capital
  @@capital_name = 'Tokyo'
  def self.capital_name
    @@capital_name
  end
  def self.change_capital_name(new_capital)
     @@capital_name = new_capital
  end
end
Capital.change_capital_name("Saitama")
p Capital.capital_name
#=> "Saitama"

クラスインスタンス変数

公式リファレンスを見る限り、クラスインスタンス変数っていう文言が見当たらないので造語なのかな🤔

特徴

  1. クラスインスタンス変数はそのクラスのみでしか参照できない。(クラスを継承したクラスではその変数にアクセスできない。)
  2. クラスメソッドからはアクセスできる
  3. インスタンスメソッドからアクセスすることはできない
  4. クラス定義式内で定義される

※詳細は、下記リンクの【まとめ】インスタンス変数、クラス変数、クラスインスタンス変数で詳しく書かれています。

参考