* Moose
- many more tests, fixing some bugs and
edge cases
-
- &extends now loads the base module with
UNIVERSAL::require
- added UNIVERSAL::require to the
dependencies list
-
- # API CHANGES #
-
+ ** API CHANGES **
- each new Moose class will also create
and register a subtype of Object which
correspond to the new Moose class.
-
- the 'isa' option in &has now only
accepts strings, and will DWIM in
almost all cases
- added tests for this
- added support for this in attributes
and instance construction
-
- # API CHANGES #
-
+ ** API CHANGES **
- type construction no longer creates a
function, it registers the type instead.
- added several functions to get the
registered types
+
+ * Moose::Object
+ - BUILDALL and DEMOLISHALL were broken
+ because of a mis-named hash key, Whoops :)
* Moose::Meta::Attribute
- adding support for coercion in the
* Moose::Meta::Class
- adding support for coercion in the
- instance construction
-
- * Moose::Object
-
- - BUILDALL and DEMOLISHALL were broken
- because of a mis-named hash key, Whoops :)
+ instance construction
+
+ * Moose::Meta::TypeConstraint
+ * Moose::Meta::TypeCoercion
+ - type constraints and coercions are now
+ full fledges meta-objects
0.01 Wed. March 15, 2006
- Moooooooooooooooooose!!!
\ No newline at end of file
=back
+=head1 BUILDING CLASSES WITH MOOSE
+
+Moose makes every attempt to provide as much convience during class
+construction/definition, but still stay out of your way if you want
+it to. Here are some of the features Moose provides:
+
+Unless specified with C<extends>, any class which uses Moose will
+inherit from L<Moose::Object>.
+
+Moose will also manage all attributes (including inherited ones) that
+are defined with C<has>. And assuming that you call C<new> which is
+inherited from L<Moose::Object>, then this includes properly initializing
+all instance slots, setting defaults where approprtiate and performing any
+type constraint checking or coercion.
+
+=head1 EXPORTED FUNCTIONS
+
+Moose will export a number of functions into the class's namespace, which
+can then be used to set up the class. These functions all work directly
+on the current class.
+
+=over 4
+
+=item B<meta>
+
+This is a method which provides access to the current class's metaclass.
+
+=item B<extends (@superclasses)>
+
+This function will set the superclass(es) for the current class.
+
+This approach is recommended instead of C<use base>, because C<use base>
+actually C<push>es onto the class's C<@ISA>, whereas C<extends> will
+replace it. This is important to ensure that classes which do not have
+superclasses properly inherit from L<Moose::Object>.
+
+=item B<has ($name, %options)>
+
+This will install an attribute of a given C<$name> into the current class.
+The list of C<%options> are the same as those provided by both
+L<Class::MOP::Attribute> and L<Moose::Meta::Attribute>, in addition to a
+few convience ones provided by Moose which are listed below:
+
+=over 4
+
+=item I<is => 'rw'|'ro'>
+
+The I<is> option accepts either I<rw> (for read/write) or I<ro> (for read
+only). These will create either a read/write accessor or a read-only
+accessor respectively, using the same name as the C<$name> of the attribute.
+
+If you need more control over how your accessors are named, you can use the
+I<reader>, I<writer> and I<accessor> options inherited from L<Moose::Meta::Attribute>.
+
+=item I<isa => $type_name>
+
+The I<isa> option uses Moose's type constraint facilities to set up runtime
+type checking for this attribute. Moose will perform the checks during class
+construction, and within any accessors. The C<$type_name> argument must be a
+string. The string can be either a class name, or a type defined using
+Moose's type defintion features.
+
+=back
+
+=item B<before $name|@names => sub { ... }>
+
+=item B<after $name|@names => sub { ... }>
+
+=item B<around $name|@names => sub { ... }>
+
+This three items are syntactic sugar for the before, after and around method
+modifier features that L<Class::MOP> provides. More information on these can
+be found in the L<Class::MOP> documentation for now.
+
+=item B<confess>
+
+This is the C<Carp::confess> function, and exported here beause I use it
+all the time. This feature may change in the future, so you have been warned.
+
+=item B<blessed>
+
+This is the C<Scalar::Uti::blessed> function, it is exported here beause I
+use it all the time. It is highly recommended that this is used instead of
+C<ref> anywhere you need to test for an object's class name.
+
+=back
+
=head1 ACKNOWLEDGEMENTS
=over 4
=over 4
+=item L<Class::MOP> documentation
+
+=item The #moose channel on irc.perl.org
+
=item L<http://forum2.org/moose/>
=back
use base 'Class::MOP::Attribute';
-__PACKAGE__->meta->add_attribute('coerce' => (reader => 'coerce'));
-__PACKAGE__->meta->add_attribute('weak_ref' => (reader => 'weak_ref'));
+__PACKAGE__->meta->add_attribute('coerce' => (reader => 'should_coerce'));
+__PACKAGE__->meta->add_attribute('weak_ref' => (reader => 'is_weak_ref' ));
__PACKAGE__->meta->add_attribute('type_constraint' => (
reader => 'type_constraint',
predicate => 'has_type_constraint',
));
-sub should_coerce { (shift)->coerce() ? 1 : 0 }
-sub is_weak_ref { (shift)->weak_ref() ? 1 : 0 }
-
__PACKAGE__->meta->add_before_method_modifier('new' => sub {
my (undef, undef, %options) = @_;
if (exists $options{coerce} && $options{coerce}) {
=head1 NAME
-Moose::Meta::Attribute - The Moose attribute metaobject
-
-=head1 SYNOPSIS
+Moose::Meta::Attribute - The Moose attribute metaclass
=head1 DESCRIPTION
This is a subclass of L<Class::MOP::Attribute> with Moose specific
-extensions.
+extensions.
+
+For the most part, the only time you will ever encounter an
+instance of this class is if you are doing some serious deep
+introspection. To really understand this class, you need to refer
+to the L<Class::MOP::Attribute> documentation.
=head1 METHODS
+=head2 Overridden methods
+
+These methods override methods in L<Class::MOP::Attribute> and add
+Moose specific features. You can safely assume though that they
+will behave just as L<Class::MOP::Attribute> does.
+
=over 4
=item B<new>
=back
+=head2 Additional Moose features
+
+Moose attributes support type-contstraint checking, weak reference
+creation and type coercion.
+
=over 4
=item B<has_type_constraint>
+Returns true if this meta-attribute has a type constraint.
+
=item B<type_constraint>
-=item B<is_weak_ref>
+A read-only accessor for this meta-attribute's type constraint. For
+more information on what you can do with this, see the documentation
+for L<Moose::Meta::TypeConstraint>.
-=item B<weak_ref>
+=item B<is_weak_ref>
-=item B<coerce>
+Returns true of this meta-attribute produces a weak reference.
=item B<should_coerce>
+Returns true of this meta-attribute should perform type coercion.
+
=back
=head1 BUGS
use strict;
use warnings;
-use Carp 'confess';
+use Carp 'confess';
+use Scalar::Util 'weaken';
our $VERSION = '0.02';
}
}
$instance->{$attr->name} = $val;
+ if (defined $val && $attr->is_weak_ref) {
+ weaken($instance->{$attr->name});
+ }
}
return $instance;
}
Moose::Meta::Class - The Moose metaclass
-=head1 SYNOPSIS
-
=head1 DESCRIPTION
This is a subclass of L<Class::MOP::Class> with Moose specific
extensions.
+For the most part, the only time you will ever encounter an
+instance of this class is if you are doing some serious deep
+introspection. To really understand this class, you need to refer
+to the L<Class::MOP::Class> documentation.
+
=head1 METHODS
=over 4
=item B<construct_instance>
-=item B<mixed_in>
+This provides some Moose specific extensions to this method, you
+almost never call this method directly unless you really know what
+you are doing.
+
+This method makes sure to handle the moose weak-ref, type-constraint
+and type coercion features.
=back
=head1 NAME
-Moose::Meta::TypeCoercion - The Moose Type Coercion metaobject
-
-=head1 SYNOPSIS
+Moose::Meta::TypeCoercion - The Moose Type Coercion metaclass
=head1 DESCRIPTION
+For the most part, the only time you will ever encounter an
+instance of this class is if you are doing some serious deep
+introspection. This API should not be considered final, but
+it is B<highly unlikely> that this will matter to a regular
+Moose user.
+
+If you wish to use features at this depth, please come to the
+#moose IRC channel on irc.perl.org and we can talk :)
+
=head1 METHODS
=over 4
=item B<new>
-=item B<coerce>
-
=item B<compile_type_coercion>
+=item B<coerce>
+
=item B<type_coercion_map>
=item B<type_constraint>
=head1 NAME
-Moose::Meta::TypeConstraint - The Moose Type Constraint metaobject
-
-=head1 SYNOPSIS
+Moose::Meta::TypeConstraint - The Moose Type Constraint metaclass
=head1 DESCRIPTION
+For the most part, the only time you will ever encounter an
+instance of this class is if you are doing some serious deep
+introspection. This API should not be considered final, but
+it is B<highly unlikely> that this will matter to a regular
+Moose user.
+
+If you wish to use features at this depth, please come to the
+#moose IRC channel on irc.perl.org and we can talk :)
+
=head1 METHODS
=over 4
=item B<new>
+=item B<compile_type_constraint>
+
+=item B<check>
+
=item B<name>
=item B<parent>
-=item B<check>
-
=item B<constraint>
=item B<has_coercion>
=item B<coercion>
-=item B<compile_type_constraint>
-
=back
=head1 BUGS
sub BUILDALL {
my ($self, %params) = @_;
- foreach my $method ($self->meta->find_all_methods_by_name('BUILD')) {
+ foreach my $method (reverse $self->meta->find_all_methods_by_name('BUILD')) {
$method->{code}->($self, %params);
}
}
Moose::Object - The base object for Moose
-=head1 SYNOPSIS
-
=head1 DESCRIPTION
+This serves as the base object for all Moose classes. Every
+effort will be made to ensure that all classes which C<use Moose>
+will inherit from this class. It provides a default constructor
+and destructor, which run all the BUILD and DEMOLISH methods in
+the class tree.
+
+You don't actually I<need> to inherit from this in order to
+use Moose though. It is just here to make life easier.
+
=head1 METHODS
=over 4
=item B<meta>
+This will return the metaclass associated with the given class.
+
=item B<new>
This will create a new instance and call C<BUILDALL>.
This will call every C<DEMOLISH> method in the inheritance hierarchy.
-=item B<NEXT>
-
=back
=head1 BUGS
to be are used in both attribute definitions and for method argument
validation.
-This is B<NOT> a type system for Perl 5.
+=head2 Important Caveat
+
+This is B<NOT> a type system for Perl 5. These are type constraints,
+and they are not used by Moose unless you tell it to. No type
+inference is performed, expression are not typed, etc. etc. etc.
+
+This is simply a means of creating small constraint functions which
+can be used to simply your own type-checking code.
+
+=head2 Default Type Constraints
This module also provides a simple hierarchy for Perl 5 types, this
could probably use some work, but it works for me at the moment.
RegexpRef
Object
-Suggestions for improvement are welcome.
+Suggestions for improvement are welcome.
=head1 FUNCTIONS
=item B<find_type_constraint ($type_name)>
-=item B<_create_type_constraint ($type_name, $type_constraint)>
-
-=item B<_install_type_coercions>
+This function can be used to locate a specific type constraint
+meta-object. What you do with it from there is up to you :)
=item B<export_type_contstraints_as_functions>
+This will export all the current type constraints as functions
+into the caller's namespace. Right now, this is mostly used for
+testing, but it might prove useful to others.
+
=back
=head2 Type Constraint Constructors
-=over 4
+The following functions are used to create type constraints.
+They will then register the type constraints in a global store
+where Moose can get to them if it needs to.
-=item B<type>
+See the L<SYNOPOSIS> for an example of how to use these.
-=item B<subtype>
+=over 4
-=item B<as>
+=item B<type ($name, $where_clause)>
-=item B<where>
+This creates a base type, which has no parent.
-=item B<coerce>
+=item B<subtype ($name, $parent, $where_clause)>
-=item B<from>
+This creates a named subtype.
-=item B<via>
+=item B<subtype ($parent, $where_clause)>
-=back
+This creates an unnamed subtype and will return the type
+constraint meta-object, which will be an instance of
+L<Moose::Meta::TypeConstraint>.
-=head2 Built-in Type Constraints
+=item B<as>
-=over 4
+This is just sugar for the type constraint construction syntax.
-=item B<Any>
+=item B<where>
-=item B<Value>
+This is just sugar for the type constraint construction syntax.
-=item B<Int>
+=back
-=item B<Str>
+=head2 Type Coercion Constructors
-=item B<Ref>
+Type constraints can also contain type coercions as well. In most
+cases Moose will run the type-coercion code first, followed by the
+type constraint check. This feature should be used carefully as it
+is very powerful and could easily take off a limb if you are not
+careful.
-=item B<ArrayRef>
+See the L<SYNOPOSIS> for an example of how to use these.
-=item B<CodeRef>
+=over 4
-=item B<HashRef>
+=item B<coerce>
-=item B<RegexpRef>
+=item B<from>
-=item B<ScalarRef>
+This is just sugar for the type coercion construction syntax.
+
+=item B<via>
-=item B<Object>
+This is just sugar for the type coercion construction syntax.
=back
use strict;
use warnings;
-use Test::More tests => 21;
+use Test::More tests => 27;
use Test::Exception;
use Scalar::Util 'isweak';
my ($self, $tree) = @_;
$tree->parent($self) if defined $tree;
};
+
+ sub BUILD {
+ my ($self, %params) = @_;
+ if ($params{parent}) {
+ # yeah this is a little
+ # weird I know, but I wanted
+ # to check the weaken stuff
+ # in the constructor :)
+ if ($params{parent}->has_left) {
+ $params{parent}->right($self);
+ }
+ else {
+ $params{parent}->left($self);
+ }
+ }
+ }
}
my $root = BinaryTree->new();
is($right->parent, $root, '... rights parent is the root');
ok(isweak($right->{parent}), '... parent is a weakened ref');
+
+my $left_left = BinaryTree->new(parent => $left);
+isa_ok($left_left, 'BinaryTree');
+
+ok($left_left->has_parent, '... left does have a parent');
+
+is($left_left->parent, $left, '... got a parent node (and it is $left)');
+ok($left->has_left, '... we have a left node now');
+is($left->left, $left_left, '... got a left node (and it is $left_left)');
+
+ok(isweak($left_left->{parent}), '... parent is a weakened ref');
+
use strict;
use warnings;
-use Test::More tests => 16;
+use Test::More tests => 20;
use Test::Exception;
BEGIN {
before after around
blessed confess
type subtype as where
+ coerce from via
+ find_type_constraint
)) {
ok(!Foo->meta->has_method($function), '... the meta does not treat "' . $function . '" as a method');
}