1. Perl
  2. オブジェクト指向プログラミング
  3. 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]

業務に役立つPerl

Perlテキスト処理のエッセンス 書籍版

関連情報