[Perl] MooseとClass::MOPでメタプログラミング始めた
今、超熱いMoose始めたよ。
で、Moose理解するにはClass::MOP理解しなきゃいけなくて、Class::MOP理解するにはMOP理解しなきゃいけないので、ircでえろい人たちに色々教わったのでメモ。
ロジックを直接コーディングするのではなく、あるパターンをもったロジックを生成する高位ロジックによってプログラミングを行う方法んで、これを実現するために必要なのがメタクラスとMOP。
MOP(メタオブジェクトプロトコル)
メタクラスを通してオブジェクトシステムへアクセスするAPI
メタクラス
クラスの振る舞いを定義したクラスでイントロスペクション(introspection)とインターセッション(itercession)を備える
イントロスペクション
オブジェクトの属性を得る能力 ex) 何のクラスを継承しているかとか、何のメソッドを持ってるかとか
インターセッション
オブジェクトの振る舞いに変更を加える能力 ex) 親クラスを変更するとか、メソッドを追加するとか。
で、Class::MOPはPerl 5のオブジェクトシステムに対してのMOPを提供してくれるモジュール。
Class::MOPには大きく分けて4つのモジュールでプロトコルが提供されてる。
Class::MOP::Class - クラスに対するプロトコル
Class::MOP::Attribute - アトリビュートに対するプロトコル
Class::MOP::Method - メソッドに対するプロトコル
Class::MOP::Instance - クラスのインスタンス生成に対するプロトコル
で、これらを使うとこんな風に書けちゃう。
use strict;
use warnings;
use Class::MOP;
{
package Hoge;
use metaclass;
}
my $meta = Hoge->meta;
my $meth_hello = Class::MOP::Method->wrap( sub { print "hello\n"; } );
my $attr_foo = Class::MOP::Attribute->new( '$foo' => ( accessor => 'foo' ) );
my $attr_bar = Class::MOP::Attribute->new( '$bar' => ( accessor => 'bar' ) );
my $hoge = Class::MOP::Instance->new($meta)->create_instance;
$meta->add_method( 'hello' => $meth_hello );
$meta->add_attribute($attr_foo);
$hoge->hello; # hello
$hoge->foo('FOO');
warn $hoge->foo; # FOO
eval { warn $hoge->bar; };
warn $@; # Can't locate object method "bar" via package "Hoge"
$meta->add_attribute($attr_bar);
$hoge->bar('BAR');
warn $hoge->bar; # BAR
で、MooseはClass::MOPをラップして使いやすくしてくれる+α的なモジュール。
use strict;
use warnings;
{
package Hoge;
use Moose;
has 'foo' => (is => 'rw');
sub hello {
my $self = shift;
print "hello\n";
}
}
my $hoge = Hoge->new;
$hoge->hello; # hello
$hoge->foo('FOO');
warn $hoge->foo; # FOO
もちろんメタクラスにアクセスできるので
$hoge->meta->add_attribute('$bar', accessor => 'bar');
$hoge->bar('BAR');
warn $hoge->bar; # BAR
てなこともできる。
すっげー便利。
参考:
Class::MOP - A Meta Object Protocol for Perl 5 - search.cpan.org
Moose - A postmodern object system for Perl 5 - search.cpan.org
meta-object-protocol
meta object protocol について考えてみる - TokuLog 改め だまってコードを書けよハゲ
