本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回はPerl 5上で先進的なオブジェクト指向を実現するためのフレームワークMooseなどの開発に関わっているShawn Moore
メタオブジェクトプロトコル(MOP)とは
さまざまなプログラミング言語がオブジェクト指向機能を提供していますが、
このような操作を行いたい場合は
MOPでは、
MOPを利用することで、
MOPの基本
それではMOPの挙動を見ていきましょう。まずMOPを使ってクラスを定義してみます。本稿では便宜上、
Class::MOPのインストール
Class::MOPは後述のMooseに同梱されているモジュールです。Mooseをインストールするにはcpanm
やcpan
コマンドを使用してCPANからインストールします。
> cpanm Moose
cpanmがインストールされていない場合は、
> 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
このようなメタクラス・