オブジェクト指向では、オブジェクトは「物」の概念をもとにしていると説明しましたが、オブジェクト指向はモノだけではなく、「継承」といった、生物的な概念も利用しています。
クラスはその子供のサブクラスに、メソッドを引き継がせることができます。親クラスをスーパークラスと呼びますが、スーパークラスで定義したメソッドは、そのままサブクラスで使うことができます。また、上書きすることもできます。スーパークラスは1つである必要がなく、複数のスーパークラスから派生したサブクラスも作成できます。
クラスを継承する
オブジェクト指向の「継承」を使えば、元のクラスの資源をもとに、新しいクラスを簡単に作成することができます。オブジェクト指向では、元になるクラスをスーパークラス、それから派生したクラスをサブクラスと呼びます。
@ISAを使って継承する
既存のクラスを継承してサブクラスを定義するには、サブクラス内で @ISAにスーパークラスの名前をセットします。
まずは、ClassA.pm という名前でスーパークラスを作成しましょう。
# ClassA を宣言(ClassB のスーパークラスになります) package ClassA; # コンストラクタの作成 sub new { my $class = shift; my $self = { x => 10 }; bless $self,$class; } # メソッドの作成 sub print_x{ my $self = shift; print $self->{x}, "\n"; } 1
次に、ClassB.pm という名前でサブクラスを作成します。
# ClassB を宣言 package ClassB ; # パッケージAの使用を宣言 use ClassA; # @ISAにスーパークラスの名前「A」を設定 # これによってクラスBはクラスAを継承する @ISA = qw ( ClassA ); # ClassB のコンストラクタ sub new { my $class = shift; # ClassA のコンストラクタを呼び出す my $self = new ClassA; return bless $self; } 1
これだけで継承が終わりました。上記のクラスB は、クラスA のメソッドを全て受け継いでいます。
それでは、ClassBのコンストラクタに注目してください。クラスに属したオブジェクトの作成で、ClassAのコンストラクタを呼び出しています。ClassA から返されたオブジェクトリファレンスをそのままClassBのインスタンス変数として bless しています。これで、ClassAのメソッド、インスタンス変数がすべてアクセス可能になりました。
ClassBを呼び出し、ClassAの print_x メソッドを利用するには次のようになります。
use ClassB; my $obj = new ClassB; # メソッドの読み出し $obj->print_x;
呼び出し側では、print_x メソッドがClassAとClassBのどちらかで定義されているかを気にする必要はありません。ただ呼び出すだけです。
スーパークラスのメソッドをオーバーライドする
スーパークラスのメソッドと同名のメソッドを定義することを、「オーバーライド」と呼びます。変数に新しい値を代入するのと同じように、スーパークラスのメソッドを上書きできます。
スーパークラスのメソッドをオーバーライド
以下の例は、スーパークラスのメソッドをオーバライドし、オーバライドされた後でそのメソッドを呼び出しています。
#--------------------------------------# # スーパークラスを定義 package Unix; sub print_x { print "UNIX! \n" } #--------------------------------------# # サブクラスを定義 package Linux; @ISA = qw( Unix ); sub new { bless {} } sub print_x { print "LINUX! \n" } #--------------------------------------# package main; my $obj = new Linux; $obj->print_x;
オーバーライドした元のメソッドを使う
サブクラスでオーバーライドされた元のメソッドは、スーパークラスを表す SUPER という擬似クラスで呼び出せます。
# スーパークラスの new メソッド呼び出し my $obj = $class->SUPER::new( $x, $y );
これでスーパークラスのコンストラクタ newメソッドが実行されます。スーパークラスのメソッドを呼び出すには、「クラス名::メソッド名」とします。モジュールからサブルーチンを参照する方法と同じ記法ですね。
多重継承
配列@ISAには複数のクラス名を設定することが出来ます。この場合、2個以上のクラスからメソッドを継承することになります。これを『多重継承』といいます。
多重継承の場合、@ISAに設定されたスーパークラスを1つづつ順に並べて、起動すべきメソッドを探します。
#--------------------------------------# # スーパークラスを定義 package Unix; sub unix { print "UNIX! \n" } #--------------------------------------# # サブクラスを定義 package Linux; @ISA = qw( Unix ); sub linux { print "Linux! \n" } #--------------------------------------# package BSD; sub bsd { print & quot;BSD! \n" } #--------------------------------------# # package Foo; @ISA = qw( Linux BSD ); @Foo::Inherit::ISA = @ISA; # オーバライドされたメソッドのアクセス sub new { bless [] } sub unix { my $self = shift; $self->Foo::Inherit::unix(); } sub linux { my $self = shift; $self->Foo::Inherit::linux(); } sub bsd { my $self = shift; $self->Foo::Inherit::bsd(); } sub os_x { print "OS X!\n" } #--------------------------------------# package main; $foo = new Foo; $foo->linux; $foo->bsd; $foo->os_x;
出力結果は下記のとおりです。
Linux! BSD! OS X