本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回はPerl 5上で先進的なオブジェクト指向を実現するためのフレームワークMooseなどの開発に関わっているShawn Moore
メタオブジェクトプロトコル(MOP)とは
さまざまなプログラミング言語がオブジェクト指向機能を提供していますが、
このような操作を行いたい場合は
MOPでは、
MOPを利用することで、
MOPの基本
それではMOPの挙動を見ていきましょう。まずMOPを使ってクラスを定義してみます。本稿では便宜上、
Class::MOPのインストール
Class::MOPは後述のMooseに同梱されているモジュールです。Mooseをインストールするにはcpanmやcpanコマンドを使用してCPANからインストールします。
> cpanm Moosecpanmがインストールされていない場合は、
> curl -Lk http://xrl.us/cpanm | perl - Mooseクラスの定義
Class::MOPを使ってクラスを定義するにはClass::MOP::Classのオブジェクトインスタンスを生成します。
このオブジェクトは
use strict;
use Class::MOP;
# (1)クラスの作成
my $meta = Class::MOP::Class->create('Person');
# (2)アトリビュートの追加
$meta->add_attribute(
'name',
accessor => 'name',
);
# (3)メソッドの追加
$meta->add_method( describe => sub {
my $self = shift;
my $name = $self->name;
print "$name";
} );
# (4)オブジェクトインスタンスの生成
my $object = $meta->new_object( name => "Shawn" );
$object->describe();
まずリスト1createには作成するクラス名を引数として渡します。
リスト1nameというアトリビュートを定義します。accessor => 'name'でこのアトリビュートにアクセスするためのアクセサ名を指定しており、reader、writerなどを指定します。
リスト1describe()を定義しました。
ここまでで一通りクラス定義ができたので、new()コンストラクタではなく、new_を使用します。リスト1new_を使用し、
クラスの継承
では、
リスト2に、
use strict;
use Class::MOP;
use Person;
# (1)クラスの作成
my $meta = Class::MOP::Class->create('Employee');
# (2)親クラスの指定
$meta->superclasses('Person');
$meta->add_attribute(
'employer',
accessor => 'employer',
);
# (3)メソッドのオーバーライド
$meta->add_method(
'describe',
sub {
my $self = shift;
my $company = $self->employer->name;
my $name = $self->name;
print "所属 $company, 社員名 $name";
# あとは親クラスにおまかせ
$self->next::method();
}
);
まずリスト2
親クラスの指定はsuperclassesというメソッドに親クラス名を指定することで実装できます。リスト2
リスト2add_をEmployeeクラスでも呼ぶことにより、mro.を使用しているので、SUPER::記法ではなくnext::methodを使っています。
メソッドモディファイア
Class::MOPでは前項のメソッドオーバーライドのほかにも
具体的にはリスト3のように、
$meta->add_before_method_modifier(
'describe',
sub {
my $self = shift;
my $company = $self->employer->name;
print "所属 $company, 社員名 ";
},
);
クラスの調査
メタクラスを利用することにより、
use strict;
use Employee;
# (
)メタクラスの取得
my $class = Employee->meta;
# "Employee"
print $class->name, "\n";
# "Person"
print $class->superclasses, "\n";
# (2)メタアトリビュート
my $attribute =
$class->find_attribute_by_name('employer');
my $accessor = $attribute->accessor;
# (3)メタメソッド
my $method = $class->find_method_by_name( $accessor );
# "employer"
print $method->name, "\n";
# "Employee::employer"
print $method->fully_qualified_name, "\n";
まずリスト4Employee->metaを呼び出します。MOPを使用して作成されたクラスには自動的にこのクラスメソッドが定義され、
リスト4find_を使用してアトリビュートを表現するオブジェクト
リスト4
このようなメタクラス・