5 use Scalar::Util 'blessed';
10 our $VERSION = '0.89_01';
11 $VERSION = eval $VERSION;
12 our $AUTHORITY = 'cpan:STEVAN';
18 use Moose::Meta::Role;
19 use Moose::Util::TypeConstraints;
22 croak "Roles do not support 'extends' (you can use 'with' to specialize a role)";
26 Moose::Util::apply_all_roles( Moose::Meta::Role->initialize(shift), @_ );
30 my $meta = Moose::Meta::Role->initialize(shift);
31 croak "Must specify at least one method" unless @_;
32 $meta->add_required_methods(@_);
36 my $meta = Moose::Meta::Role->initialize(shift);
37 croak "Must specify at least one role" unless @_;
38 $meta->add_excluded_roles(@_);
42 my $meta = Moose::Meta::Role->initialize(shift);
44 croak 'Usage: has \'name\' => ( key => value, ... )' if @_ == 1;
45 my %options = ( definition_context => Moose::Util::_caller_info(), @_ );
46 my $attrs = ( ref($name) eq 'ARRAY' ) ? $name : [ ($name) ];
47 $meta->add_attribute( $_, %options ) for @$attrs;
50 sub _add_method_modifier {
52 my $meta = Moose::Meta::Role->initialize(shift);
56 croak "Roles do not currently support "
58 . " references for $type method modifiers"
60 my $add_method = "add_${type}_method_modifier";
61 $meta->$add_method( $_, $code );
65 sub before { _add_method_modifier('before', @_) }
67 sub after { _add_method_modifier('after', @_) }
69 sub around { _add_method_modifier('around', @_) }
71 # see Moose.pm for discussion
73 return unless $Moose::SUPER_BODY;
74 $Moose::SUPER_BODY->(@Moose::SUPER_ARGS);
78 my $meta = Moose::Meta::Role->initialize(shift);
79 my ( $name, $code ) = @_;
80 $meta->add_override_method_modifier( $name, $code );
84 croak "Roles cannot support 'inner'";
88 croak "Roles cannot support 'augment'";
91 Moose::Exporter->setup_import_methods(
93 qw( with requires excludes has before after around override )
96 qw( extends super inner augment ),
98 \&Scalar::Util::blessed,
106 my $role = $args{for_class};
110 Moose->throw_error("Cannot call init_meta without specifying a for_class");
113 my $metaclass = $args{metaclass} || "Moose::Meta::Role";
115 # make a subtype for each Moose class
116 role_type $role unless find_type_constraint($role);
118 # FIXME copy from Moose.pm
120 if ($role->can('meta')) {
121 $meta = $role->meta();
123 unless ( blessed($meta) && $meta->isa('Moose::Meta::Role') ) {
125 Moose->throw_error("You already have a &meta function, but it does not return a Moose::Meta::Role");
129 $meta = $metaclass->initialize($role);
133 # re-initialize so it inherits properly
134 $metaclass->initialize( ref($_[0]) || $_[0] );
150 Moose::Role - The Moose Role
155 use Moose::Role; # automatically turns on strict and warnings
160 my ($self, $other) = @_;
161 !$self->equal($other);
164 # ... then in your classes
167 use Moose; # automatically turns on strict and warnings
172 my ($self, $other) = @_;
173 $self->as_float == $other->as_float;
178 The concept of roles is documented in L<Moose::Manual::Roles>. This document
179 serves as API documentation.
181 =head1 EXPORTED FUNCTIONS
183 Moose::Role currently supports all of the functions that L<Moose> exports, but
184 differs slightly in how some items are handled (see L<CAVEATS> below for
187 Moose::Role also offers two role-specific keyword exports:
191 =item B<requires (@method_names)>
193 Roles can require that certain methods are implemented by any class which
196 Note that attribute accessors also count as methods for the purposes
197 of satisfying the requirements of a role.
199 =item B<excludes (@role_names)>
201 Roles can C<exclude> other roles, in effect saying "I can never be combined
202 with these C<@role_names>". This is a feature which should not be used
209 Moose::Role offers a way to remove the keywords it exports, through the
210 C<unimport> method. You simply have to say C<no Moose::Role> at the bottom of
211 your code for this to work.
213 =head2 B<< Moose::Role->init_meta(for_class => $role, metaclass => $metaclass) >>
215 The C<init_meta> method sets up the metaclass object for the role
216 specified by C<for_class>. It also injects a a C<meta> accessor into
217 the role so you can get at this object.
219 The default metaclass is L<Moose::Meta::Role>. You can specify an
220 alternate metaclass with the C<metaclass> parameter.
224 When you use Moose::Role, you can specify which metaclass to use:
226 use Moose::Role -metaclass => 'My::Meta::Role';
228 You can also specify traits which will be applied to your role metaclass:
230 use Moose::Role -traits => 'My::Trait';
232 This is very similar to the attribute traits feature. When you do
233 this, your class's C<meta> object will have the specified traits
234 applied to it. See L<Moose/Metaclass and Trait Name Resolution> for more
239 Role support has only a few caveats:
245 Roles cannot use the C<extends> keyword; it will throw an exception for now.
246 The same is true of the C<augment> and C<inner> keywords (not sure those
247 really make sense for roles). All other Moose keywords will be I<deferred>
248 so that they can be applied to the consuming class.
252 Role composition does its best to B<not> be order-sensitive when it comes to
253 conflict resolution and requirements detection. However, it is order-sensitive
254 when it comes to method modifiers. All before/around/after modifiers are
255 included whenever a role is composed into a class, and then applied in the order
256 in which the roles are used. This also means that there is no conflict for
257 before/around/after modifiers.
259 In most cases, this will be a non-issue; however, it is something to keep in
260 mind when using method modifiers in a role. You should never assume any
267 All complex software has bugs lurking in it, and this module is no
268 exception. If you find a bug please either email me, or add the bug
273 Stevan Little E<lt>stevan@iinteractive.comE<gt>
275 Christian Hansen E<lt>chansen@cpan.orgE<gt>
277 =head1 COPYRIGHT AND LICENSE
279 Copyright 2006-2009 by Infinity Interactive, Inc.
281 L<http://www.iinteractive.com>
283 This library is free software; you can redistribute it and/or modify
284 it under the same terms as Perl itself.