Smalltalk、Ruby、Pythonのような動的型付けオブジェクト指向プログラミング言語の特徴にダックタイピング(Duck Typing)というものがあります。なんでこんな名前がついたのかというと、「家鴨(Duck)のように歩いて、鳴くのだから、これはきっと家鴨に違いない」という、台詞からきています。
さて、C++のような静的型付けオブジェクト指向言語では、クラスの継承によって、オブジェクトが何であるかを認識します。例えば、非常に良く似たクラスAとBがあったとします。このとき、クラスAを引数として取る関数testを定義します。このとき、クラスBのオブジェクトを渡して、呼び出すことができません。
class A { public: void methodA(){ printf( "methodA on A\n" ); } }; class B { public: void methodA(){ printf( "methodA on B\n" ); } }; void test(A *obj) { obj->methodA(); } // A *a = new A; B *b = new B; test( a ); // 正常 test( b ); // エラー
この場合、ベースになるクラスを作って継承することで、汎用化した関数を書くことができます。
class Base { public: virtual void methodA() = 0; }; class A : Base { public: void methodA(){ printf( "methodA on A\n" ); } }; class B : Base{ public: void methodA(){ printf( "methodA on B\n" ); } }; void test(Base *obj) { obj->methodA(); } // A *a = new A; B *b = new B; test( a ); // 正常(AはBaseから継承されているから) test( b ); // 正常(BもBaseから継承されているから)
PHPの場合は、動的型付けオブジェクト指向言語ですから、こんな面倒なことをする必要はありません。同じように呼出できるメソッドがあれば、同じクラスのように振舞います。
class A { function methodA(){ print "methodA on A\n"; } } class B { function methodA(){ print "methodA on B\n"; } } function test($obj) { $obj->methodA(); } $a = new A; $b = new B; test($a); test($b);
さてRubyではこのあたりの考え方をさらに一歩押し進めて、動的にクラスにメソッドを追加できるようになっています。以下は組み込みの文字列であるStringクラスにメソッドを追加した例です。
class String def methodA() print "methodA on String" end end "string".methodA() // methodA on String
ここまでくると気をつけないととんでもない拡張をしてしまって後でこまることになります。しかし、工夫次第では非常に面白いこともできます。このNumericクラスの追加は、組み込みの数値クラスに、ヤードポンド法の重さの単位を扱えるようにした拡張です。
class Numeric def lb self * 453.59237 ; end def oz self.lb/16 end def gr self.lb/7000 end end print "#{124.lb + 4.oz}\n" print "#{55.gr}\n"
このあたりの自由度の高さが、Ruby信者が生まれる原因でもありますし、一方では厳密さを好むjavaの信者などには嫌われるところです。ウィザード言語万歳(w
(by yna)