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)