- Perl ›
- オブジェクト指向プログラミング ›
- here
mro - next::methodの有効化・メソッド解決順序の変更
mro
モジュールは、多重継承における、スーパークラスのメソッド解決順序を変更するためのモジュールです。mro
を読み込むと、next::method
が有効になります。多重継承で、スーパークラスのメソッドを探索する場合はSUPER疑似クラスよりも、next::method
うことが推奨されています。
# next::methodの有効化 use mro;
next::method
は、オブジェクトから呼び出します。
# next::methodの使い方 $self->next::method(@args);
next::methodの動作
next::method
は、C3というアルゴリズムで、スーパークラスを探索します。
C3 は常に局所的な優先順位を保存して動作します。 これは、基本的にどのクラスもそのサブクラスより先に現れることはないことを 意味します。 例えば、以下のような古典的なダイヤ型継承パターンを考えます: <A> / \ <B> <C> \ / <D> 標準の Perl 5 MRO は (D, B, A, C) です。 この結果、C は A のサブクラスにも関わらず、A が C より先に 検索されます。 しかし、C3 MRO アルゴリズムでは、(D, B, C, A) の順序になり、この問題は ありません。
参考:C3 の動作 - mro
next::methodを多重継承で使ったサンプル
next::method
を多重継承で使ったサンプルです。
use strict; use warnings; use mro; package MultiBase1 { sub b1_init { my $self = shift; push @{$self->{ps}}, 2; $self->{b1} = 3; } } package MultiBase2 { sub b1_init { my $self = shift; push @{$self->{ps}}, 7; $self->{b1} = 8; } sub b2_init { my $self = shift; push @{$self->{ps}}, 3; $self->{b2} = 4; } } package MultiClass { use base 'MultiBase1', 'MultiBase2'; sub new { my $class = shift; my $self = bless {@_}, ref $class || $class; $self->{ps} //= []; $self->init; return $self; } sub init { my $self = shift; push @{$self->{ps}}, 1; $self->b1_init; $self->b2_init; } sub b1_init { my $self = shift; $self->next::method; } sub b2_init { my $self = shift; $self->next::method; } } my $object = MultiClass->new; print $object->{b1} . "\n"; # 3 print $object->{b2} . "\n"; # 4 print "@{$object->{ps}}" . "\n"; # [1, 2, 3]