Moose > Moose::Cookbook::Basics::Recipe11

題名

Moose::Cookbook::Basics::Recipe11 - Mooseを使っていないベースクラスを拡張する

概要

  package My::DateTime;

  use Moose;
  extends qw( DateTime Moose::Object );

  use DateTime::Calendar::Mayan;

  has 'mayan_date' => (
      is        => 'ro',
      isa       => 'DateTime::Calendar::Mayan',
      init_arg  => undef,
      lazy      => 1,
      builder   => '_build_mayan_date',
      clearer   => '_clear_mayan_date',
      predicate => 'has_mayan_date',
  );

  sub new {
      my $class = shift;

      my $obj = $class->SUPER::new(@_);

      return $class->meta->new_object(
          __INSTANCE__ => $obj,
          @_,
      );
  }

  after 'set' => sub {
      $_[0]->_clear_mayan_date;
  };

  sub _build_mayan_date {
      DateTime::Calendar::Mayan->from_object( object => $_[0] );
  }

本文

このレシピではMooseを利用してMooseベースではない親クラスをサブクラス化する方法を説明します。このレシピでうまく行くのは親クラスがblessされたハッシュリファレンスの場合のみです。親クラスがちょっと変わったことをしている場合はMooseX::InsideOutを試してみてください。

また、MooseX::NonMooseを試してみてもよいかもしれません。これを使うと面倒な作業はすべてやってくれます。

いくつか注釈を入れておきたい箇所があります。

  use Moose;
  extends qw( DateTime Moose::Object );

まず、いつものようにuse Mooseします。こうするとアトリビュートを宣言したり、おなじみのシュガー関数をすべて利用できるようになります。

extendsの宣言にはDateTimeだけでなく、明示的にMoose::Objectを入れておきます。こうすると、doesのようにMoose::Objectが提供しているメソッドも使えるようになります。

コンストラクタにはMooseを使っていない親クラスを使うときに特有のハック/パターン(ハックたん?)が見られます。

  sub new {
      my $class = shift;

      my $obj = $class->SUPER::new(@_);

      return $class->meta->new_object(
          __INSTANCE__ => $obj,
          @_,
      );
  }

ここでは明示的に$class->meta->new_objectを呼んで、作成済みのオブジェクトを__INSTANCE__キーとともに渡しています。内部的にはMooseが既存のオブジェクトを受け取り、あればサブクラスで定義されているアトリビュートの初期化を行います。

afterモディファイアは期待通りの動作をします。setがMooseを使っていない親クラスで定義されていても問題ありません。

まとめ

Mooseは、ここで紹介したパターンにしたがえば、Mooseを使っていないクラスともうまく共存できます。アトリビュートの宣言、メソッドモディファイア、(新しいアトリビュートの)型制約、ロールといったMooseの力は、サブクラスの中でもすべて利用できます。

ただし、親クラスの「アトリビュート」はMooseのアトリビュートではありませんから、簡単にはオーバーライドできません。また、コンストラクタをインライン展開することもできません。メタクラスのオブジェクトコンストラクタを明示的に利用する必要があるためです。

作者

Dave Rolsky <autarch@urth.org>

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

Copyright 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.