OOP(5) 共通祖先 UNIVERSAL
use Student;
my $palmo = Student->new();
$palmo->doit();
というコードが書かれているのにもかかわらず、Student クラスに doit メソッドが定義されていない時、C++などのOOP言語ではコンパイルエラーとなりますが、Perl ではエラーにならない場合があります。
その場合の1つが「doit メソッドが UNIVERSAL クラスに定義されていた場合」です。というのも、全てのクラスは UNIVERSAL クラスを暗黙的に継承しているからだそうです。
メソッドが呼び出されて、そのメソッドがクラスに定義されていない場合、Perl はまず @ISA をたどって、親クラスに定義されているかを再帰的に調べます。親クラスに定義されていれば、それをそのまま実行するので、これが「継承」のメカニズムになっているわけですね。
ただ、@ISA を全てたどってもメソッドが見つからない場合……Perl は次に UNIVERSAL クラスを調べます。つまり、@ISA に指定されなくても UNIVERSAL も継承元として自動的に調べられるのです。
そして、UNIVERSAL クラスに目的のメソッドが定義されていたら、通常の継承と同じように、そのメソッドを呼び出します。
UNIVERSAL クラスを試しに使ってみます。
package Student;
sub new {
$class = shift;
bless { }, $class;
}
package main;
sub UNIVERSAL::doit {
print "Universal has done it.\n";
}
my $palmo = Student->new();
$palmo->doit();
Student はコンストラクタ new だけを持っていて、メソッド doit は定義されていません。にもかかわらず、package main では生成した Student オブジェクトに対して doit メソッドの呼び出しを行っています。
もし、UNIVERSAL が暗黙のうちに継承されるのであれば、UNIVERSAL::doit(UNIVERSAL パッケージ空間での doit 関数 = UNIVERSAL クラスの doit メソッド)が実行されるはずです。
以下、実行結果です。
Universal has done it.
ちゃんとエラーも出さずに UNIVERSAL::doit メソッドが呼ばれていますね。
UNIVERSAL の組み込み済みメソッドについては明日勉強します。(^_^;)