Roleの使いどころ

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を利用するときって結構共通の
コードが出たりする。でもこの方法であったら、本当に独立な部分をくくり
出すことができるので、すっきりと書けるのではないかと思います。