メソッド
Rubyのメソッドの定義は.NETより単純です。型を指定しないからです。
irb(main):001:0> def greet(name) irb(main):002:1> puts "Hello, #{name}!" irb(main):003:1> end => nil irb(main):004:0> greet "Reader" Hello, Reader! => nil irb(main):005:0> greet 42 Hello, 42! => nil
Rubyでは、「Duck Typing(ダックタイピング)」と呼ばれるものが行われます。これは、「アヒルのように歩き、アヒルのように鳴くものはアヒルに違いない」という格言に由来する概念です。相手がアヒルであるかどうかを問うようなことはしません。ただ相手をアヒルと見なして、「ガーガー鳴く」動作を呼び出します。たとえ相手がアヒルでなかったとしても、ガーガーと鳴くことができるものであれば何でも良しとします。
上のgreet
メソッドの定義では、渡すことができるオブジェクトの型に何も制限を設けていないことに注意してください。これは渡されたオブジェクトを出力するだけのメソッドですが、RubyではあらゆるものがObjectのto_s
メソッド(オブジェクトを文字列に変換するメソッド)のおかげで出力をサポートしているため、渡されるオブジェクトが何であってもgreet
を実行できます。つまり、相手が何であっても挨拶(greet
)ができるというわけです。
次にもう1つの例を示します。
irb(main):006:0> def print_len(item) irb(main):007:1> puts "Len = #{item.length}" irb(main):008:1> end => nil irb(main):009:0> print_len "Reader" Len = 6 => nil irb(main):010:0> print_len [1, 4, 9] Len = 3 => nil irb(main):011:0> print_len 42 NoMethodError: undefined method <span class="pf">'</span>length' for 42:Fixnum from (irb):7:in <span class="pf">'</span>print_len' from (irb):11
print_len
メソッドは前より多くの働きをするようになっています。このメソッドは、渡されたオブジェクトのlength
メソッドを呼び出します。従って、print_len
に渡すオブジェクトは、パラメータなしで呼び出せるlength
メソッドを持っていることが要件になります。文字列や配列を渡した場合は正しく処理されます。これらのオブジェクトは必要なlength
メソッドを持っているからです。しかし、数値を渡すと正しく処理されません。数値にはlength
メソッドがないからです。
このようなメソッドを.NETで記述する場合は、おそらくIHaveLength
インターフェイスを用意して、それをパラメータ型として使う必要があるでしょう。インターフェイスを用意する前に作成されたクラスについては、あきらめるか、型コンバータを作成することになります。厳密な型指定の仕組みが間に立ちはだかると、たちまちすべてが手に負えない状況に陥ります。
その一方で、少なくともIHaveLength
があれば、メソッドの要件が何かは分かります。型は一種のドキュメントの役目を果たすので、動的言語では代わりの手段が必要です。つまり、あるクラスやメソッドがどのような使われ方をすべきものかを見極めるために、書かれたドキュメントや単体テストなどに頼ることになります。
Rubyでは、引数のデフォルト値がサポートされています。
irb(main):012:0> def repeat(val, times = 5) irb(main):013:1> val.to_s * times irb(main):014:1> end => nil irb(main):015:0> repeat "hi" => "hihihihihi" irb(main):016:0> repeat "hi", 3 => "hihihi" irb(main):017:0> repeat 10, 3 => "101010"
val.to_s * times
の前にreturn
がないことに注意してください。Rubyのメソッドは、値を返すように明示的に指定されていない限り、常に最後の評価の結果を返します。このため、return
キーワードをあえて入力する必要はありません。
Rubyでは、可変引数がサポートされています。
irb(main):018:0> def add(*values) irb(main):019:1> result = 0 irb(main):020:1> values.each {|x| result += x} irb(main):021:1> result irb(main):022:1> end => nil irb(main):023:0> add 1, 2, 3, 4, 5 => 15
可変引数はまとめて配列に格納されます。これにより、渡された値にアクセスし、(この例では)それらの値を合計できます。
メソッドと変数の命名規則
Rubyのメソッド名は小文字で始まり、名前には英数字とアンダースコアを使うことができます。
名前の末尾に感嘆符(!
)が付いたメソッドは、基になるオブジェクトの状態を変更します。例えば、文字列のupcase
メソッドは文字列を大文字に変換して返しますが、元の文字列の状態は変更しません。これに対し、upcase!
メソッドは、基になる文字列を実際に変更します。
名前の末尾に疑問符(?
)が付いたメソッドは、質問に答えるような処理(真偽値を返す処理)を行います。