メソッド
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!メソッドは、基になる文字列を実際に変更します。
名前の末尾に疑問符(?)が付いたメソッドは、質問に答えるような処理(真偽値を返す処理)を行います。
