【Ruby入門】Rubyのインスタンス変数とクラス変数

Rubyのクラスにおける、インスタンス変数とクラス変数について説明します。

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

インスタンス変数とクラス変数の最も大きな違いは、インスタンス毎に値が固有であるか否かにあります。

具体的のは、以下のようになります。

  • インスタンス毎に値が固有:インスタンス変数
  • インスタンス毎に値が共通:クラス変数

次から、インスタンス変数とクラス変数について、それぞれ説明していきます。

インスタンス変数とは

インスタンス変数に値を保存しておけば、そのインスタンスごとに固有の値を保持することができます。

インスタンス変数の定義

クラスの中でインスタンス変数を定義するには、「@」のあとに、通常の変数と同じ命名規則で変数を定義します。

class クラス名
  def メソッド名
    @name = 値
  end
end

インスタンス変数へのアクセス

インスタンス変数には、オブジェクトの外から直接アクセスすることはできません。そのため、インスタンス変数にアクセスするためのメソッド(アクセサー)をクラスに定義する必要があります。

たとえば、車についての情報を管理する「Car」というクラスを作り、インスタンスごとに別々の「車名」を管理しておきたい場合、次のようにインスタンス変数「@name」を定義します。

class Car
  #インスタンス変数@nameに値をセットする
  def setName(str)
    @name = str
  end 

  #インスタンス変数@nameを表示する
  def dispName
    puts @name
  end
end

car1 = Car.new
car1.setName("Legacy")

car2 = Car.new
car2.setName("XV")

car1.dispName #=> Legacy
car2.dispName #=> XV

Carクラスからインスタンスを作成し、setNameメソッドでインスタンス変数@nameに名前を代入し、dispNameメソッドで名前を表示します。

重要なのは、インスタンス変数はインスタンスごとに別の値を持っているという点です。

attr_accessorを使ったインスタンス変数

上記の例では、アクセサーをクラスに定義していますが、単純なアクセサーであればattr_accessorを使うことで自動的に定義することができます。

class Car
  attr_accessor :name
end

car1 = Car.new
car1.name = "Legacy"
puts car1.name

書式は以下のような形で、複数のインスタンス変数を定義する場合は、カンマ「,」で区切ります。

class クラス名
  attr_accessor :変数名1, :変数名2
end

また、読み込み専用のattr_readerや書き込み専用のattr_writerなどもあります。

クラス変数とは

インスタンス変数がインスタンスごとに固有の値を保持するのに対し、クラス変数はそのクラスと継承をしたサブクラス、インスタンスで共有できる変数です。

クラス変数の定義

クラス変数は、@@から始まる英数字またはアンダースコアで以下のように書きます。

class クラス名
  @@name = 値
end

「@@name」に格納した値は、このクラスから生成したインスタンスのすべてで共有されます。ただし、この変数を読み書きできるのは、基本的に、自分のクラスとサブクラスのクラス定義、クラスメソッド、インスタンスメソッドからのみです。

クラス変数の使い方

それでは、クラス変数はどのように使えばいいのでしょうか? 実例を挙げてみましょう。

class Car
  @@engine = "gasoline"

  def dispCarEngine
    puts @@engine
  end
end

class LightCar < Car

  def changeEngine
    ##クラス変数をgasolineからelectricに変更
    @@engine = "electric"
  end

  def dispLightCarEngine
    puts @@engine
  end
end

s1 = LightCar.new
s1.changeEngine
s1.dispLightCarEngine #=> electric

s2 = Car.new
s2.dispCarEngine #=> electric

クラス変数として@@engineを持つCarクラスとCarクラスを継承したLightCarクラスがあります。

LightCarのインスタンスs1が、クラス変数@@engineを変更するchangeEngineメソッドを実行することで、Carクラスのs2のdispCarEngineメソッドの結果もgasolineからelectricになっています。