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 の組み込み済みメソッドについては明日勉強します。(^_^;)