Rubyのクラスにおける、インスタンス変数とクラス変数について説明します。
インスタンス変数とクラス変数の違い
インスタンス変数とクラス変数の最も大きな違いは、インスタンス毎に値が固有であるか否かにあります。
具体的のは、以下のようになります。
- インスタンス毎に値が固有:インスタンス変数
- インスタンス毎に値が共通:クラス変数
次から、インスタンス変数とクラス変数について、それぞれ説明していきます。
インスタンス変数とは
インスタンス変数に値を保存しておけば、そのインスタンスごとに固有の値を保持することができます。
インスタンス変数の定義
クラスの中でインスタンス変数を定義するには、「@」のあとに、通常の変数と同じ命名規則で変数を定義します。
1 2 3 4 5 |
class クラス名 def メソッド名 @name = 値 end end |
インスタンス変数へのアクセス
インスタンス変数には、オブジェクトの外から直接アクセスすることはできません。そのため、インスタンス変数にアクセスするためのメソッド(アクセサー)をクラスに定義する必要があります。
たとえば、車についての情報を管理する「Car」というクラスを作り、インスタンスごとに別々の「車名」を管理しておきたい場合、次のようにインスタンス変数「@name」を定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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を使うことで自動的に定義することができます。
1 2 3 4 5 6 7 |
class Car attr_accessor :name end car1 = Car.new car1.name = "Legacy" puts car1.name |
書式は以下のような形で、複数のインスタンス変数を定義する場合は、カンマ「,」で区切ります。
1 2 3 |
class クラス名 attr_accessor :変数名1, :変数名2 end |
また、読み込み専用のattr_readerや書き込み専用のattr_writerなどもあります。
クラス変数とは
インスタンス変数がインスタンスごとに固有の値を保持するのに対し、クラス変数はそのクラスと継承をしたサブクラス、インスタンスで共有できる変数です。
クラス変数の定義
クラス変数は、@@から始まる英数字またはアンダースコアで以下のように書きます。
1 2 3 |
class クラス名 @@name = 値 end |
「@@name」に格納した値は、このクラスから生成したインスタンスのすべてで共有されます。ただし、この変数を読み書きできるのは、基本的に、自分のクラスとサブクラスのクラス定義、クラスメソッド、インスタンスメソッドからのみです。
クラス変数の使い方
それでは、クラス変数はどのように使えばいいのでしょうか? 実例を挙げてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
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になっています。