+package Moose::Cookbook::Basics::Recipe11;
-=pod
+# ABSTRACT: Extending a non-Moose base class
-=head1 NAME
+__END__
-Moose::Cookbook::Basics::Recipe11 - Using BUILDARGS and BUILD to hook into object construction
-=head1 SYNOPSIS
+=pod
- package Person;
+=begin testing-SETUP
- has 'ssn' => (
- is => 'ro',
- isa => 'Str',
- predicate => 'has_ssn',
- );
+use Test::Requires {
+ 'DateTime' => '0',
+ 'DateTime::Calendar::Mayan' => '0',
+ 'MooseX::NonMoose' => '0',
+};
- has 'country_of_residence' => (
- is => 'ro',
- isa => 'Str',
- default => 'usa'
- );
+=end testing-SETUP
- has 'first_name' => (
- is => 'ro',
- isa => 'Str',
- );
+=head1 SYNOPSIS
- has 'last_name' => (
- is => 'ro',
- isa => 'Str',
- );
+ package My::DateTime;
- sub BUILDARGS {
- my $class = shift;
+ use Moose;
+ use MooseX::NonMoose;
+ extends qw( DateTime );
- if ( @_ == 1 && ! ref $_[0] ) {
- return { ssn => $_[0] };
- }
- else {
- return $class->SUPER::BUILDARGS(@_);
- }
- }
+ 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 BUILD {
- my $self = shift;
+ after 'set' => sub {
+ $_[0]->_clear_mayan_date;
+ };
- if ( $self->country_of_residence eq 'usa' ) {
- die 'Cannot create a Person who lives in the USA without an ssn.'
- unless $self->has_ssn;
- }
+ sub _build_mayan_date {
+ DateTime::Calendar::Mayan->from_object( object => $_[0] );
}
=head1 DESCRIPTION
-This recipe demonstrates the use of C<BUILDARGS> and C<BUILD>. By
-defining these methods, we can hook into the object construction
-process without overriding C<new>.
-
-The C<BUILDARGS> method is called I<before> an object has been
-created. It is called as a class method, and receives all of the
-parameters passed to the C<new> method. It is expected to do something
-with these arguments and return a hash reference. The keys of the hash
-must be attribute C<init_arg>s.
-
-The primary purpose of C<BUILDARGS> is to allow a class to accept
-something other than named arguments. In the case of our C<Person>
-class, we are allowing it to be called with a single argument, a
-social security number:
-
- my $person = Person->new('123-45-6789');
-
-The key part of our C<BUILDARGS> is this conditional:
-
- if ( @_ == 1 && ! ref $_[0] ) {
- return { ssn => $_[0] };
- }
-
-By default, Moose constructors accept a list of key-value pairs, or a
-hash reference. We need to make sure that C<$_[0]> is not a reference
-before assuming it is a social security number.
-
-We call C<< $class->SUPER::BUILDARGS(@_) >> to handle all the other
-cases. You should always do this in your own C<BUILDARGS> methods,
-since L<Moose::Object> provides its own C<BUILDARGS> method that
-handles hash references and a list of key-value pairs.
-
-The C<BUILD> method is called I<after> the object is constructed, but
-before it is returned to the caller. The C<BUILD> method provides an
-opportunity to check the object state as a whole. This is a good place
-to put logic that cannot be expressed as a type constraint on a single
-object.
-
-In the C<Person> class, we need to check the relationship between two
-attributes, C<ssn> and C<country_of_residence>. We throw an exception
-if the object is not logically consistent.
-
-=head1 MORE CONSIDERATIONS
-
-This recipe is made significantly simpler because all of the
-attributes are read-only. If the C<country_of_residence> attribute
-were settable, we would need to check that a Person had an C<ssn> if
-the new country was C<usa>. This could be done with a C<before>
-modifier.
-
-=head1 CONCLUSION
-
-We have repeatedly discouraged overriding C<new> in Moose
-classes. This recipe shows how you can use C<BUILDARGS> and C<BUILD>
-to hook into object construction without overriding C<new>
-
-The C<BUILDARGS> method lets us expand on Moose's built-in parameter
-handling for constructors. The C<BUILD> method lets us implement
-logical constraints across the whole object after it is created.
+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::NonMoose::InsideOut> and L<MooseX::InsideOut>.
-=head1 AUTHOR
+The meat of this recipe is contained in L<MooseX::NonMoose>, which does all
+the grunt work for you.
-Dave Rolsky E<lt>autarch@urth.orgE<gt>
+=begin testing
-=head1 COPYRIGHT AND LICENSE
+my $dt = My::DateTime->new( year => 1970, month => 2, day => 24 );
-Copyright 2006-2009 by Infinity Interactive, Inc.
+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' );
-L<http://www.iinteractive.com>
+$dt->set( year => 2009 );
+ok( ! $dt->has_mayan_date, 'mayan_date is cleared after call to ->set' );
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
+=end testing
=cut