初雪が降り始めた街の中で,僕は立ち尽くしていた。彼女から暗号メールで別れを切り出されて以来,連絡が思うように取れていない。わずかな希望にすがり,僕から暗号メールを送信してみたが,まだ返事はない。僕はだんだん状況を正確に判断できなくなってきているのかもしれない。そこで,何かアドバイスが得られるかもしれないと思い,大学以来の友人Kに電話をしてみた。
僕:「彼女からの返事が,まだ来ない」
K:「そう,君はどんな気分だい?」
僕:「とても不安だよ。彼女は返事する気がないのだろうか。あるいは暗号が解けていないのだろうか。全くわからない」
K:「そう,それから?」
僕:「どうしようもなく困り果てている」
K:「ふむ…。なるほど。では,気晴らしに有名なパズルを僕から送ろう」
僕:「また,暗号かい?」
K:「いや,暗号ではないが,割と有名なパズルだよ。メールで問題を送付するから待っていてくれ」
最近の僕は,彼女のことになると,どうしても少し取り乱してしまう。友人Kがどんなパズルを送ってくるかはわからない。でもパズルでも解いて,気を落ち着かせた方がよいのだろう。友人Kからメールが届くまでの間,僕はまたRubyについて思いをめぐらせることにした。
Rubyの継承について復習しよう
前回,Rubyの過激な一面であるオープンクラスについて述べた。今回は,Rubyにおける多重継承について考えたい。その前に,オブジェクト指向プログラミングで重要な継承と多重継承を補足しておこう。
継承については以前から何度も触れているが,簡単に言ってしまえば親の機能を子に引き継ぐための機能だ。継承の実例を,整数のクラスを使って見てみよう。
Rubyの整数には,2種類のクラスが用意されている。FixnumクラスとBignumクラスだ。この二つのクラスの違いは,扱える整数の大きさにある。通常利用する整数は,ほとんどがFixnumクラスになる。これは,31ビットで収まる整数までを扱える。
それ以上の大きな整数を扱いたい場合は,Bignumクラスを利用することになる。対象となるクラスが何であるかを確認するには「class」メソッドを用いればわかる。実際に,整数のクラスを確認してみよう。リスト1のようになる。Rubyのすごいところは,FixnumクラスからBignumクラスへ自動で変換してくれるところだ。あなたが「今の数値はFixnumクラスで扱える値か,またはBignumクラスにするべきか?」ということを意識する必要はない。Fixnumクラスの値を超えると,自動でBignumクラスに変換してくれるのだ。
1.class #-> Fixnum
12345678901234567890.class #-> Bignum
FixnumクラスとBignumクラスは,基本的に扱える数値の大きさが異なるだけなので,機能(つまり保持するメソッド)は,ほとんど同じものを備えていると想像したくなる。実際に,この二つのクラスは,ほぼ同じメソッドを保持している。例えば,to_sという自分自身の文字列表現を返すメソッドや,to_fという浮動小数点表現を返すメソッドなどがそれに当たる。
二つのクラスがあるから同じメソッドをFixnumクラス用に作成し,さらにBignumクラス用にもう一度作成するのは非常に面倒だ。僕ならば共通に定義して,それをFixnumとBignumのそれぞれのクラスが呼び出せるようにしたいと思えてくる。
こんなときに使えるのが継承なのだ。共通の機能などを親クラスで定義しておき,子クラス(FixnumとBignum)はその親から継承を使って,機能を引き継げばよいのである。FixnumとBignumの親クラスを調べてみるとわかるように,この二つのクラスは同じIntegerという親クラスを共有している*1。試しにリスト2のように記述して,親クラスを調べてみよう。
1.class.superclass #-> Integer
12345678901234567890.class.superclass #-> Integer
継承を利用すれば,共通の機能は親クラスで定義し,個別の機能は子クラスの方で定義する,という効率的かつ便利な機能のまとめ方が可能になる。また,あなたがFixnumクラスやBignumクラス以外の新しい整数クラスを定義したい場合,FixnumクラスやBignumクラスと同様にIntegerクラスを継承すれば,同じ機能をわざわざ定義する必要がなくなるわけだ。
個人的な意見になるが,継承は非常に便利な機能だったからこそ,オブジェクト指向が注目を集め始めた当初は「オブジェクト指向といえば継承である」という見方をされていたのではないかと思う。