doh, forgot to actually add the recipe itself
Dave Rolsky [Fri, 3 Apr 2009 05:41:20 +0000 (00:41 -0500)]
lib/Moose/Cookbook/Basics/Recipe12.pod [new file with mode: 0644]

diff --git a/lib/Moose/Cookbook/Basics/Recipe12.pod b/lib/Moose/Cookbook/Basics/Recipe12.pod
new file mode 100644 (file)
index 0000000..3ad3282
--- /dev/null
@@ -0,0 +1,138 @@
+
+=pod
+
+=begin testing-SETUP
+
+BEGIN {
+    eval 'use DateTime; use DateTime::Calendar::Mayan;';
+    if ($@) {
+        diag 'DateTime & DateTime::Calendar::Mayan required for this test';
+        ok(1);
+        exit 0;
+    }
+}
+
+=end testing-SETUP
+
+=head1 NAME
+
+Moose::Cookbook::Basics::Recipe12 - Extending a non-Moose base class
+
+=head1 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] );
+  }
+
+=head1 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 L<MooseX::InsideOut>.
+
+There are a couple pieces worth noting:
+
+  use Moose;
+  extends qw( DateTime Moose::Object );
+
+First, we C<use Moose> just like we always do. This lets us declare
+attributes and use all the Moose sugar to which we are accustomed.
+
+The C<extends> declaration explicitly include L<Moose::Object> as well
+as L<DateTime>. This lets us use methods which are provided by
+L<Moose::Object>, like C<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 C<< $class->meta->new_object >> and pass the
+already-created object in the C<__INSTANCE__> key. Internally, Moose
+will take the existing object and initialize any attributes defined in
+our subclass.
+
+The C<after> modifier works just like we'd expect. The fact that
+C<set> is defined in our non-Moose parent does not matter.
+
+=head1 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.
+
+=head1 AUTHOR
+
+Dave Rolsky E<lt>autarch@urth.orgE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2009 by Infinity Interactive, Inc.
+
+L<http://www.iinteractive.com>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=begin testing
+
+my $dt = My::DateTime->new( year => 1970, month => 2, day => 24 );
+
+can_ok( $dt, 'mayan_date' );
+isa_ok( $dt->mayan_date, 'DateTime::Calendar::Mayan' );
+is( $dt->mayan_date->date, '12.17.16.9.19', 'got expected mayan date' );
+
+$dt->set( year => 2009 );
+ok( ! $dt->has_mayan_date, 'mayan_date is cleared after call to ->set' );
+
+=end testing
+
+=cut