演算子とメソッド
Rubyの演算子の中には、本体の処理はメソッドとして定義されており演算子としての姿は糖衣構文に過ぎないものがいくつか存在します。以下に再掲した演算子表のうち赤いドットを打っている演算子がメソッドです。
出典: 前出『パーフェクトRuby』p.73
たとえばメソッドとして定義されている演算子の一例として比較演算子「<
」に着目してみます。
2番目の書き方でも動くことから、1 < 2
という書き方は「レシーバ1に対して、引数2をとってメソッド<
を呼び出す」処理にほかならないことがわかります。
演算子の再定義
演算子もメソッドであるということは、そのメソッド表現さえ特定してしまえば好きなように再定義することが出来ます。
本記事では例として「==
」演算子(メソッド)を再定義して、通常と異なる動きをさせてみます。まず普通にオブジェクト同士を==
で比較すると何が起こるかを見てみましょう。
何も継承せずクラスを定義した時、その親クラスは Object, Kernel, BasicObject
となります。一番プリミティブな==
が定義されているのはBasicObjectクラスで、ドキュメントによればその定義は次の通りです。
Equality---At the Object level,
==
returns true only if obj and other are the same object.
つまり ==
は左右が同じオブジェクトの時のみtrueを返します。上記のGreetingインスタンスはまさにこの通りの挙動を示しています。
さて次に、Greetingクラス特有の==
メソッドを定義してみましょう。元気よく(最後に!
をつけて)挨拶していれば等しい挨拶とみなすことにします。
演算子==
の結果が変わったことが確認できます。
このような実装は特殊な用例に見えるかもしれませんが、表から見えづらいだけで、実際のところいろいろな場所で使われています。たとえば「===
」メソッドは各クラス・モジュールで再定義され、case文の表現力向上に一役買っています。参考: Rubyのcase式と===演算子について - しばそんノート。
以上
以上でRubyの演算子についての記事は終わりです。演算子の一部がメソッドとして実装されていることで柔軟な拡張を可能としているんだな、となんとなく実感できれば幸いです。Rubyの設計は潜ってみると「あれ、見た目は違うけどこの設計思想は別の場所でも聞いたな」ということが多々あり、他の例も探ってみると面白いかもしれません。