Moose::Cookbook::Basics::Recipe11(3p)

NAME
Moose::Cookbook::Basics::Recipe11 - Extending a non-Moose base class

SYNOPSIS
  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] );
  }

DESCRIPTION
This recipe demonstrates how to use Moose to subclass a parent which is not Moose based. This recipe only works if the parent class uses a blessed hash reference for object instances. If your parent is doing something funkier, you should check out MooseX::InsideOut.

You might also want to check out MooseX::NonMoose, which does all the grunt work for you.

There are a couple pieces worth noting:

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

First, we "use Moose" just like we always do. This lets us declare attributes and use all the Moose sugar to which we are accustomed.

The "extends" declaration explicitly include Moose::Object as well as DateTime. This lets us use methods which are provided by Moose::Object, like "does".

The constructor demonstrates a particular hack/pattern (hacktern?) for working with non-Moose parent classes:

  sub new {
      my $class = shift;

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

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

We explicitly call "$class->meta->new_object" and pass the already-created object in the "__INSTANCE__" key. Internally, Moose will take the existing object and initialize any attributes defined in our subclass.

The "after" modifier works just like we'd expect. The fact that "set" is defined in our non-Moose parent does not matter.

CONCLUSION
Moose can play nice with non-Moose classes when you follow the pattern shown here. Your subclass has access to all the power of Moose, including attribute declaration, method modifiers, type constraints (for new attributes), and roles.

However, you won't be able to easily override a parent's "attributes", since they're not Moose attributes. Nor will you be able to inline a constructor, since you need to explicitly use the metaclass's object constructor.

AUTHOR
Dave Rolsky <autarch@urth.org>

COPYRIGHT AND LICENSE
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.