クラス
クラスは、新しいオブジェクトインスタンスを生成するときに使われる雛型です。例えば、前のgreet
メソッドをクラスに入れるには、次のように記述します。
irb(main):001:0> class Manners irb(main):002:1> def greet(name) irb(main):003:2> puts "Hello, #{name}!" irb(main):004:2> end irb(main):005:1> end => nil irb(main):006:0> m = Manners.nRew => #<Manners:0x404839c> irb(main):007:0> m.greet "Reader" Hello, Reader! => nil
このコードでは、Manners
という新しいクラスを作成し、そこにgreet
メソッドを追加しています。その後、Manners
の新しいインスタンスを生成し、そのインスタンスを使って挨拶を表示しています。
Rubyのクラスはオブジェクトの生きた雛型であると考えてください。コンパイル時に定義される.NETのクラスと異なり、Rubyのクラスはいつでも拡張できます。クラスを拡張すると、そのクラスの既存のインスタンスにも直ちに新しい振る舞いが追加されます。別れの言葉(farewell
)を表示しようとするとどのようなことが起きるか考えてみましょう。
irb(main):008:0> m.farewell "Reader" NoMethodError: undefined method 'farewell' for #<Manners:0x404839c> from (irb):8
farewell
を呼び出そうとすると、そのようなメソッドはないというメッセージが表示されます。そこで、Manners
クラスを拡張し、別れの言葉を表示する機能を追加します。
irb(main):009:0> class Manners irb(main):010:1> def farewell(name) irb(main):011:2> puts "Goodbye, #{name}!" irb(main):012:2> end irb(main):013:1> end => nil irb(main):014:0> m.farewell "Reader" Goodbye, Reader! => nil
Manners
クラスを拡張した後は、クラスの既存のインスタンスもfarewell
を呼び出せるようになっています。
Manners
クラスには2つのメソッドがあり、どちらも名前(name
)を引数として受け取ります。おそらく、生成時に名前を渡せるようにクラスを書き換えた方がいいでしょう。new
に渡したすべての引数を使ってinitialize
メソッドが呼び出されるようにします。変更後のManners
クラスは次のようになります。
irb(main):001:0> class Manners irb(main):002:1> def initialize(name) irb(main):003:2> @name = name irb(main):004:2> end irb(main):005:1> def greet irb(main):006:2> puts "Hello, #{@name}!" irb(main):007:2> end irb(main):008:1> def farewell irb(main):009:2> puts "Goodbye, #{@name}!" irb(main):010:2> end irb(main):011:1> end => nil irb(main):012:0> m = Manners.new "Reader" => #<Manners:0x809fa08 @name="Reader"> irb(main):013:0> m.greet Hello, Reader! => nil irb(main):014:0> m.farewell Goodbye, Reader! => nil
クラスは@name
というインスタンス変数に名前を格納します。また、インスタンスの内容表現(12行目の後に表示される結果)には、すべてのインスタンス変数の値が含まれます。
クラスの拡張性は、自分で定義したクラスだけにとどまりません。Rubyの組み込みクラスを拡張することもできます。
irb(main):001:0> class Array irb(main):002:1> def print_tr irb(main):003:2> puts "<tr>" irb(main):004:2> each { |item| irb(main):005:3* puts " <td>#{item}</td>" irb(main):006:3> } irb(main):007:2> puts "</tr>" irb(main):008:2> end irb(main):009:1> end => nil Irb(main):010:0> ["hello","world!"].print_tr <tr> <td>hello</td> <td>world!</td> </tr> => nil
Railsの組み込みの型には、自然なインターフェイスを提供する多くの拡張が追加されています。例えば、5.days.from_now
のようなコードを書いて、タイムゾーンに対応した、今から5日後の日付を取得できます。
これまで定義してきたメソッドは、すべてインスタンスメソッドでした。つまり、クラスのインスタンスに対してのみ利用できるメソッドでした。Rubyには、静的メソッド(クラスメソッドも呼ばれます)もあります。実は、この記事でも既に静的メソッドをそれとは意識せずに呼び出しています。new
メソッドのことです。
次のように、新しい静的メソッドを既存のクラスに追加できます。
irb(main):001:0> def String.concat(s1, s2) irb(main):002:1> s1 + ' ' + s2 irb(main):003:1> end => nil irb(main):004:0> String.concat 'hi', 'bye' => "hi bye"
また、「self」構文を使って、クラスを定義または拡張するコンテキストで静的メソッドを定義することもできます。
irb(main):001:0> class String irb(main):002:1> def self.concat(s1, s2) irb(main):003:2> s1 + ' ' + s2 irb(main):004:2> end irb(main):005:1> end => nil irb(main):006:0> String.concat 'hi', 'bye' => "hi bye"