Rubyにおける継承(Java/C++との比較)
JavaやC++において継承というと、仕様(インターフェース)の継承がメインだ。
public interface Printable { public void print(); } public class Number implements Printable { int number = 100; public void print() { System.out.println(number); } } public class Text implements Printable { String str = "hello"; public void print() { System.out.println(str); } }
とこんな感じにしておくと、Number,TextどちらもPrintableのインスタンスとして扱える。以下の関数はインスタンスがNumberでも、Textでも受け取る事ができる。
void function(Printable printable)
{
printable.print();
}
これは何のためにやってるのかというと、ポリモーフィズムの実現のためだ。型を気にすることなくprint();とすればその内容を表示することができる。C++の場合はinterfaceがないので純粋仮想関数しか持たないクラスを作る。
なぜこういうことをするかというと、静的型付けを行う言語だから。例えば上の例でfunctionの引数の型がNumberだとコンパイルエラーになってしまう。
Number num = new Number(); Text text = new Text(); function(number); function(text); //コンパイルエラー
これをrubyで無理やりおんなじ様に書こうとすると、
class Number @@num = 100; def printvalue print @@num end end class Text @@str = "hello" def printvalue print @@str end end def function(param) param.printvalue end num = Number.new text = Text.new function(num) function(text)
こんなことになるがこれはナンセンス。rubyの様な動的型付け言語ではもっと簡単に書ける。
num = 100 text = "hello" def function(param) print param end function(num) function(text)
function()にパラメータを渡すときに型チェックをしないので、わざわざ同じinterfaceを継承していなくてもパラメータを渡すことができ、同じ名前のメソッドさえあればポリモーフィズムを実現できる。
よって、rubyの様な動的型付け言語では「継承」とはインターフェースの継承ではなく実装の継承に使われる。