7. クラスとオブジェクト(2)
2012/11/14 シナジーマーケティング(株) 松尾 裕美
7章 クラスとオブジェクト
- 7.1. オブジェクト指向型言語におけるクラス
- 7.2. クラスの定義
- 7.3. インスタンスメソッド
- 7.4. インスタンス変数
- 7.5. オブジェクトの生成、インスタンスメソッドの呼び出し
- 7.6. アクセサメソッド
- 7.7. initializeメソッド
- 7.8. クラス変数、クラスメソッド
7.6 アクセサメソッド
前ページでは、インスタンス変数に値をセットしたり、値を返す為のアクセサメソッドを定義しましたが、インスタンス変数の数が多くなるとその分アクセサメソッドが必要になることもあります。
そこで、Rubyではインスタンス変数にアクセスするメソッドを、以下のメソッドを呼び出すことで簡単に定義することができます。
attr_writer(引数) | インスタンス変数書き込み用メソッドを定義 |
attr_reader(引数) | インスタンス変数読み取り用メソッドを定義 |
attr_accessor(引数) | インスタンス変数書き込み用メソッド、読み取り用メソッドの両方を定義 |
引数には、アクセサメソッドを作りたい変数名を、「"変数名"」か「:変数名」1で指定します。
上記プログラムでインスタンス変数nameとageに対するアクセサメソッドを定義しましたが、
attr_accessorを使うと以下のように省略して書くことができます。
# coding: windows-31j class Human # これだけでname、ageのアクセサメソッドが定義できる attr_accessor :name ,:age # 名前と年齢を表示するメソッド def print_name_age puts "名前は#{@name}です。年は#{@age}歳です。" end end taro = Human.new taro.name = "太郎" # 「name=」メソッドの呼び出し taro.age = 30 # 「age=」メソッドの呼び出し taro.print_name_age
■実行結果
名前は太郎です。年は30歳です。
7.7 initializeメソッド
前ページのプログラムでは、オブジェクトを生成したあと、インスタンス変数に値をセットするメソッドを呼び出しましたが、オブジェクト生成と同時に値をセットした方が利便性が高い場合もあります。
そのために、「initilalize」という名前の特殊なメソッドを定義しておきます。initializeメソッドはオブジェクト生成時に呼び出されるメソッドです。
例えば、先ほどのHumanクラスにinitilalizeメソッドを定義すると、以下のようになります。
# coding: windows-31j class Human attr_accessor :name ,:age # 引数がなかった場合はデフォルト値が入るように設定 def initialize(myname = "anonymous", myage = 0) @name = myname @age = myage end def print_name_age puts "名前は#{@name}です。年は#{@age}歳です。" end end taro = Human.new("太郎", 30) # initializeメソッド呼び出し taro.print_name_age anominous = Human.new # 引数がないため、initializeメソッドの引数にはデフォルト値が入る。 anominous.print_name_age
■実行結果
名前は太郎です。年は30歳です。
名前はanonymous です。年は0歳です。
7.8 クラス変数、クラスメソッド
クラスには、インスタンス変数やインスタンスメソッドのほかに、「クラス変数」「クラスメソッド」という、クラスが持っている変数やメソッドがあります。
クラス変数やクラスメソッドは、クラスから作成されたオブジェクトに共通の変数やメソッドとなります。
Rubyでは「@@」から始まる変数をクラス変数とみなします。
また、クラスメソッドは以下のように、「self.メソッド名」か「クラス名.メソッド名」と定義します。
def self.メソッド名 # 「def クラス名.メソッド名」でも可能 式 end
クラスメソッドを呼び出す場合は、「クラス名.メソッド名」で呼び出します。
クラス変数やクラスメソッドの使用法ですが、例えばHumanクラスからオブジェクトが何個作成されたかをカウントしたい場合、インスタンス変数にカウントした値を入れてしまうとインスタンスごとに異なる変数を持ってしまうため、個数の一元管理ができません。
そこで、クラス変数にカウントした値を入れておき、オブジェクトが生成されるごとにクラス変数の値をカウントアップしていけばいいのです。
# coding: windows-31j class Human # オブジェクト作成個数を格納するクラス変数 @@object_count = 0 # 作成されたオブジェクトの個数を出力するクラスメソッド def self.print_count puts "生成されたオブジェクト数は#{@@object_count}個です" end attr_accessor :name ,:age def initialize (myname = "anonymous ", myage = 0) @name = myname @age = myage @@object_count += 1 # オブジェクト作成ごとにカウントアップ end def print_name_age puts "名前は#{@name}です。年は#{@age}歳です。" end end taro = Human.new("太郎", 30) taro.print_name_age anominous = Human.new anominous.print_name_age Human.print_count
■実行結果
名前は太郎です。年は30歳です。
名前はanonymous です。年は0歳です。
生成されたオブジェクト数は2個です
1 「:変数名」の書き方を「シンボル」といいます。詳しくは後の章で説明しますが、文字列と1対1で紐づくオブジェクトです。文字列と似ていますが、文字列そのものを操作する場合でなければ、シンボルの方が内部的な処理として効率がいいです。