Moose-0.92 > Moose::Cookbook::Roles::Recipe2

題名

Moose::Cookbook::Roles::Recipe2 - 高度なロールの合成――メソッドの排除と別名

概要

  package Restartable;
  use Moose::Role;

  has 'is_paused' => (
      is      => 'rw',
      isa     => 'Bool',
      default => 0,
  );

  requires 'save_state', 'load_state';

  sub stop { 1 }

  sub start { 1 }

  package Restartable::ButUnreliable;
  use Moose::Role;

  with 'Restartable' => {
      -alias => {
          stop  => '_stop',
          start => '_start'
      },
      -excludes => [ 'stop', 'start' ]
  };

  sub stop {
      my $self = shift;

      $self->explode() if rand(1) > .5;

      $self->_stop();
  }

  sub start {
      my $self = shift;

      $self->explode() if rand(1) > .5;

      $self->_start();
  }

  package Restartable::ButBroken;
  use Moose::Role;

  with 'Restartable' => { -excludes => [ 'stop', 'start' ] };

  sub stop {
      my $self = shift;

      $self->explode();
  }

  sub start {
      my $self = shift;

      $self->explode();
  }

本文

この例では、ロールのどのメソッドを取り込むを細かくコントロールするやり方を説明します。ここではRestartableというロールを用意しました。これにはis_pausedというアトリビュートと、stopstartという2つのメソッドがあります。

それから、もう2つ、インタフェースは同じですが、それぞれstopメソッドとstartメソッドにひねりを加えたロールを用意します。

Restartable::ButUnreliableロールではstopstartの実装を新しくしつつ、もともとの実装も利用できるようにしたいので、Restartableのメソッドに別名をつけてプライベートメソッドにし、もとのメソッドの方にラッパを用意することにします。(1)

  with 'Restartable' => {
      -alias => {
          stop  => '_stop',
          start => '_start'
      },
      -excludes => [ 'stop', 'start' ]
  };

Restartable::ButBrokenロールの方では、stopstartの振る舞いを一新したいので、Restartable::ButBrokenRestartableロールを合成するときにstopstartを完全に排除してしまいます。

-excludesパラメータは、排除したいメソッドがひとつだけの場合は引数に単一の文字列を取ることができることも特記しておきます。

  with 'Restartable' => { -excludes => [ 'stop', 'start' ] };

まとめ

排除と別名は強力なツールですし、特にほかのロールからロールを生成する場合には便利に使えます。この例では、すべてのロールがRestartableロールを実装しています。どのロールもAPIは同じですが、それぞれ裏では異なった実装になっています。

別名と排除の機能は、ロールをクラスに合成するときも使えます。

1

ラッパに言及したことからおわかりの通り、メソッドモディファイアを利用しても同じことができますが、この例ではそうしていません。

作者

Dave Rolsky <autarch@urth.org>

コピーライト & ライセンス

Copyright 2006-2009 by Infinity Interactive, Inc.

http://www.iinteractive.com

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.