Moose::Roleは Javaでいうところの Interfaceみたいに使うものと思って
いたけど、もうちょっと高度なことにも使える。Interfaceだと、とにかく
決められたメソッドを実装するということになるけど、Roleだとそこに
あるメソッドを定義して、そのメソッドに必要となるメソッドの実装を
要求するという使い方もできる。Moose::ManualかMoose::Cookbookあたりに
載ってました。
で、サンプルを書いてみました。
package YAMLDumper; use Moose::Role; requires qw(as_yaml); no Moose::Role; use YAML; sub yaml_dump { my $self = shift; print YAML::Dump($self->as_yaml); } 1; package SampleClass; use Moose; with 'YAMLDumper'; has name => ( is => 'rw', isa => 'Str', required => 1, ); has hobby => ( is => 'rw', isa => 'Str', required => 1, ); has _internal_data => ( is => 'rw', isa => 'Int', ); my $id; sub BUILD { my $self = shift; $self->_internal_data( $id++ ); } __PACKAGE__->meta->make_immutable; no Moose; sub as_yaml { my $self = shift; return { name => $self->name, hobby => $self->hobby, }; } 1; package main; my $obj = SampleClass->new(name => 'Yamada', hobby => 'Baseball'); $obj->yaml_dump;
普通に YAML::Dumpしてもいいですが、モジュールの利用者に見えて
欲しくないデータがあるものとします。YAMLで出力する部分は Roleの
部分で作っておいて、YAML化の部分の実装をそれぞれに委ねるという
ものですね。
僕が未熟な面もあるんですが、Interfaceを利用するときって結構共通の
コードが出たりする。でもこの方法であったら、本当に独立な部分をくくり
出すことができるので、すっきりと書けるのではないかと思います。