Perl Hackers Hub
第13回 メタオブジェクトプロトコル入門(1)
本連載では第一線の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のオブジェクトインスタンスを生成します。
このオブジェクトは
リスト1 MOPによるクラスの定義
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に,
リスト2 MOPによるサブクラスの定義
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のように,
リスト3 メソッドモディファイア
$meta->add_before_method_modifier(
'describe',
sub {
my $self = shift;
my $company = $self->employer->name;
print "所属 $company, 社員名 ";
},
);
クラスの調査
メタクラスを利用することにより,
リスト4 MOPでクラスを調べる
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
このようなメタクラス・
バックナンバー
Perl Hackers Hub
- 第64回 少しマニアックなPerlのテクニック―特殊変数,低レベルの標準関数を使いこなす(2)
- 第64回 少しマニアックなPerlのテクニック―特殊変数,低レベルの標準関数を使いこなす(1)
- 第63回 PPIとPerl::Tidyを組み合わせて作るコード整形ツール(2)
- 第63回 PPIとPerl::Tidyを組み合わせて作るコード整形ツール(1)
- 第62回 Perl歴史散策 ―インタプリタの実装と,構文の進化をたどる(3)
- 第62回 Perl歴史散策 ―インタプリタの実装と,構文の進化をたどる(2)
- 第62回 Perl歴史散策 ―インタプリタの実装と,構文の進化をたどる(1)
- 第61回 GitHub ActionsとAmazon ECSを使ったDockerアプリケーションの自動デプロイ(3)
- 第61回 GitHub ActionsとAmazon ECSを使ったDockerアプリケーションの自動デプロイ(2)
- 第61回 GitHub ActionsとAmazon ECSを使ったDockerアプリケーションの自動デプロイ(1)