モダンなクラス/オブジェクトのあり方は?
Perlではそもそもオブジェクトという考え方自体が,
ただし,
今回はそのようなクラス/
継承によるクラスの拡張
伝統的なbaseプラグマを使ってクラスを拡張する場合,
use strict;
use warnings;
package ClassA;
sub initialize { print "A"; }
package ClassB;
use base 'ClassA';
sub initialize { print "B"; }
package main;
ClassB->initialize; # B
ただし,
use strict;
use warnings;
package ClassA;
sub initialize { print "A"; }
package ClassB;
use base 'ClassA';
sub initialize { print "B"; shift->SUPER::initialize; }
package main;
ClassB->initialize; # BA
- ※1
疑似クラスといっても普通に使っている分にはピンと来ないかもしれませんが,
要するにSUPER::initialize(shift)のような使い方はできない, ということです。詳しくはperldoc perlobjをご覧ください。
SUPERの問題点
ただ,
use strict;
use warnings;
package ClassA;
sub initialize { print "A"; }
package ClassB;
sub initialize { print "B"; }
package ClassC;
use base qw(ClassA ClassB);
sub initialize { print "C"; shift->SUPER::initialize; }
package main;
ClassC->initialize; # CA
本当はClassAのinitializeも,
もちろん継承の仕方を変えて,
そこで登場したのがNEXTというモジュールでした。
NEXTの登場
NEXTは,
use strict;
use warnings;
use NEXT;
package ClassA;
sub initialize { print "A"; shift->NEXT::initialize; }
package ClassB;
sub initialize { print "B"; shift->NEXT::initialize; }
package ClassC;
use base qw(ClassA ClassB);
sub initialize { print "C"; shift->NEXT::initialize; }
package main;
ClassC->initialize; # CAB
このように,
NEXTの問題点
ところが,
use strict;
use warnings;
use NEXT;
package ClassA;
sub initialize { print "A"; shift->NEXT::initialize; }
package ClassB;
use base qw(ClassA);
sub initialize { print "B"; shift->NEXT::initialize; }
package ClassC;
use base qw(ClassA);
sub initialize { print "C"; shift->NEXT::initialize; }
package ClassD;
use base qw(ClassB ClassC);
sub initialize { print "D"; shift->NEXT::initialize; }
package main;
ClassD->initialize; # DBACA
このコードでもすでに一階層深いAがCより先に実行される
このような不安定さは,