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.