Rubyでは演算子の多くが普通にメソッドとして定義されているので、「+」や「-」などの二項演算子などは普通に再定義することが可能となります。
演算子を定義する前にまずは再定義できる演算子とできない演算子があることを知っておく必要があります。再定義できない演算子は下記の通りです。
1 |
= ?: .. ... not && and || or :: |
詳細は下記のページに掲載されるので一度目を通しておくと良いでしょう。演算子の優先順位なども書いてあるのでとても参考になります。
るりま | 演算子式
それではまず下記のスクリプトで「+」や「-」もメソッド名として作ることができるということを確認しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class A def a "a" end def + "sum" end def - "subtraction" end end obj = A.new p obj.a p obj.+ p obj.- |
"a" "sum" "subtraction"
17、18行目を見てみるとメソッド「a」と同じように「+」「-」がメソッドとして機能していることがわかります。また、この場合ではメソッド「+」「-」自体には特に足したり引いたりの意味はありません。ただただ「+」「-」を使ってメソッドを実行しているだけになります。
オブジェクトを作って足し算みたいなことをしてみる
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class B def initialize(a = 0) @a = a end def +(b) @a + b end end obj = B.new(1) p obj p obj.+(1) p obj + 1 # シンタックスシュガー |
#<B:0x00000000976918 @a=1> 2 2
11、12行目をみてみると「B」クラスのクラスメソッド「new」が使われて、インスタンス変数「@a」が定義されてオブジェクトが変数「obj」に格納されていることがわかります。ここに13行目のように記述すると+(b)メソッドが実行され、2が返ってきます。
14行目は13行目の記述のシンタックスシュガーとなっています。これでいよいよ、足し算っぽくなってきましたね。
整数の足し算の挙動を変えてみる
さっきまでのは新しく自分でクラスを作ってオブジェクトも作って足し算をしていましたが、次は実際に整数の足し算の挙動を変えてみようと思います。
まず、初めに「1」や「2」がどのクラスのオブジェクトとなっているかを確認していきましょう。「class」メソッドを使うとそのオブジェクトのクラスを調べることができます。
1 2 3 |
p 1.class p 2.class p 0.class |
Fixnum Fixnum Fixnum
これで整数は「Fixnum」というクラスのオブジェクトになっていることがわかりました。
普通に足し算してみる
次に「Fixnum」クラスのオブジェクト「1」と「2」を普通に足してみます。
1 |
p 1 + 2 |
3
上記の結果を見てみると普通に足し算が行われていることがわかりますね。
「Fixnum」クラスを再定義
ここから「Fixnum」クラスをオーバーライドして挙動を変更してみます。
1 2 3 4 5 6 7 8 9 |
class Fixnum def +(other) "#{self}"+"#{other}" end end p 1 + 2 a = 1 + 2 p a.class |
"12" String
これで整数同士の計算のはずが文字列「”12″」として返ってきました。(実際のところやる意味は全くありませんが。。)このように「+」などの二項演算子などは本来とは別の意味合いに変更することもRubyではできたりします。
「Fixnum」クラスの再定義について
今回「1 + 2」を行っていますが実際には「1.+(2)」という感じになっています。
1 2 3 4 |
# さっきの「class Fixnum」は省略 p 1.class p 1.+(2) p 1.+(2).class |
Fixnum "12" String
これによってFixnumクラスのオブジェクト「1」に+メソッドの「2」を引数として渡す流れになります。この時点では両方とも整数(Fixnumクラスのオブジェクト)となりますが、+メソッドを実行して「1」「2」を文字列に変更し、文字列同士を+で連結させています。
なお、selfはレシーバ自身を参照するので「1」となりそこに引数「2」が文字列として加えられることになります。また、「+(other)」の「other」は二項演算子を定義する際に慣習的に用いられているようです。
コメントを残す