bump version to 0.77
[gitmo/Moose.git] / lib / Moose / Role.pm
CommitLineData
e185c027 1
2package Moose::Role;
3
4use strict;
5use warnings;
6
e65dccbc 7use Scalar::Util 'blessed';
f4f808de 8use Carp 'croak';
e185c027 9
2d562421 10use Sub::Exporter;
11
75d2da34 12our $VERSION = '0.77';
e606ae5f 13$VERSION = eval $VERSION;
d44714be 14our $AUTHORITY = 'cpan:STEVAN';
e185c027 15
d7d8a8c7 16use Moose ();
17use Moose::Util ();
e65dccbc 18
c36b393c 19use Moose::Exporter;
e185c027 20use Moose::Meta::Role;
7eaef7ad 21use Moose::Util::TypeConstraints;
e185c027 22
e606ae5f 23sub extends {
24 croak "Roles do not currently support 'extends'";
25}
26
27sub with {
28 Moose::Util::apply_all_roles( Moose::Meta::Role->initialize(shift), @_ );
29}
30
31sub requires {
32 my $meta = Moose::Meta::Role->initialize(shift);
33 croak "Must specify at least one method" unless @_;
34 $meta->add_required_methods(@_);
35}
36
37sub excludes {
38 my $meta = Moose::Meta::Role->initialize(shift);
39 croak "Must specify at least one role" unless @_;
40 $meta->add_excluded_roles(@_);
41}
2d562421 42
e606ae5f 43sub has {
44 my $meta = Moose::Meta::Role->initialize(shift);
45 my $name = shift;
46 croak 'Usage: has \'name\' => ( key => value, ... )' if @_ == 1;
47 my %options = @_;
48 my $attrs = ( ref($name) eq 'ARRAY' ) ? $name : [ ($name) ];
49 $meta->add_attribute( $_, %options ) for @$attrs;
50}
2d562421 51
e606ae5f 52sub before {
53 my $meta = Moose::Meta::Role->initialize(shift);
54 my $code = pop @_;
fb1e11d5 55
e606ae5f 56 for (@_) {
b8945921 57 croak "Roles do not currently support "
e606ae5f 58 . ref($_)
59 . " references for before method modifiers"
60 if ref $_;
61 $meta->add_before_method_modifier( $_, $code );
62 }
63}
2d562421 64
e606ae5f 65sub after {
66 my $meta = Moose::Meta::Role->initialize(shift);
2d562421 67
e606ae5f 68 my $code = pop @_;
69 for (@_) {
b8945921 70 croak "Roles do not currently support "
e606ae5f 71 . ref($_)
72 . " references for after method modifiers"
73 if ref $_;
74 $meta->add_after_method_modifier( $_, $code );
2d562421 75 }
e606ae5f 76}
fb1e11d5 77
e606ae5f 78sub around {
79 my $meta = Moose::Meta::Role->initialize(shift);
80 my $code = pop @_;
81 for (@_) {
b8945921 82 croak "Roles do not currently support "
e606ae5f 83 . ref($_)
84 . " references for around method modifiers"
85 if ref $_;
86 $meta->add_around_method_modifier( $_, $code );
87 }
88}
fb1e11d5 89
e606ae5f 90# see Moose.pm for discussion
91sub super {
92 return unless $Moose::SUPER_BODY;
93 $Moose::SUPER_BODY->(@Moose::SUPER_ARGS);
94}
95
96sub override {
97 my $meta = Moose::Meta::Role->initialize(shift);
98 my ( $name, $code ) = @_;
99 $meta->add_override_method_modifier( $name, $code );
100}
101
102sub inner {
b8945921 103 croak "Roles cannot support 'inner'";
e606ae5f 104}
105
106sub augment {
b8945921 107 croak "Roles cannot support 'augment'";
e606ae5f 108}
109
c36b393c 110Moose::Exporter->setup_import_methods(
e606ae5f 111 with_caller => [
112 qw( with requires excludes has before after around override make_immutable )
113 ],
114 as_is => [
115 qw( extends super inner augment ),
116 \&Carp::confess,
117 \&Scalar::Util::blessed,
118 ],
119);
120
121sub init_meta {
122 shift;
123 my %args = @_;
124
70ea9161 125 my $role = $args{for_class};
126
127 unless ($role) {
128 require Moose;
129 Moose->throw_error("Cannot call init_meta without specifying a for_class");
130 }
e606ae5f 131
132 my $metaclass = $args{metaclass} || "Moose::Meta::Role";
133
134 # make a subtype for each Moose class
135 role_type $role unless find_type_constraint($role);
136
137 # FIXME copy from Moose.pm
138 my $meta;
139 if ($role->can('meta')) {
140 $meta = $role->meta();
70ea9161 141
142 unless ( blessed($meta) && $meta->isa('Moose::Meta::Role') ) {
143 require Moose;
144 Moose->throw_error("You already have a &meta function, but it does not return a Moose::Meta::Role");
145 }
e606ae5f 146 }
147 else {
148 $meta = $metaclass->initialize($role);
149
150 $meta->add_method(
151 'meta' => sub {
152 # re-initialize so it inherits properly
153 $metaclass->initialize( ref($_[0]) || $_[0] );
d31f9614 154 }
e606ae5f 155 );
d31f9614 156 }
e606ae5f 157
158 return $meta;
e185c027 159}
160
1611;
162
163__END__
164
165=pod
166
167=head1 NAME
168
169Moose::Role - The Moose Role
170
76d37e5a 171=head1 SYNOPSIS
172
173 package Eq;
85424612 174 use Moose::Role; # automatically turns on strict and warnings
fb1e11d5 175
e46edf94 176 requires 'equal';
fb1e11d5 177
178 sub no_equal {
76d37e5a 179 my ($self, $other) = @_;
180 !$self->equal($other);
181 }
fb1e11d5 182
76d37e5a 183 # ... then in your classes
fb1e11d5 184
76d37e5a 185 package Currency;
85424612 186 use Moose; # automatically turns on strict and warnings
fb1e11d5 187
76d37e5a 188 with 'Eq';
fb1e11d5 189
76d37e5a 190 sub equal {
191 my ($self, $other) = @_;
bdabd620 192 $self->as_float == $other->as_float;
76d37e5a 193 }
194
e185c027 195=head1 DESCRIPTION
196
85424612 197Role support in Moose is pretty solid at this point. However, the best
198documentation is still the the test suite. It is fairly safe to assume Perl 6
199style behavior and then either refer to the test suite, or ask questions on
200#moose if something doesn't quite do what you expect.
d44714be 201
85424612 202We are planning writing some more documentation in the near future, but nothing
203is ready yet, sorry.
76d37e5a 204
2c0cbef7 205=head1 EXPORTED FUNCTIONS
206
85424612 207Moose::Role currently supports all of the functions that L<Moose> exports, but
208differs slightly in how some items are handled (see L<CAVEATS> below for
209details).
76d37e5a 210
85424612 211Moose::Role also offers two role-specific keyword exports:
e185c027 212
213=over 4
214
2c0cbef7 215=item B<requires (@method_names)>
76d37e5a 216
fb1e11d5 217Roles can require that certain methods are implemented by any class which
85424612 218C<does> the role.
9e93dd19 219
2c0cbef7 220=item B<excludes (@role_names)>
221
9e93dd19 222Roles can C<exclude> other roles, in effect saying "I can never be combined
fb1e11d5 223with these C<@role_names>". This is a feature which should not be used
85424612 224lightly.
9e93dd19 225
2c0cbef7 226=back
227
d31f9614 228=head2 B<unimport>
229
230Moose::Role offers a way to remove the keywords it exports, through the
231C<unimport> method. You simply have to say C<no Moose::Role> at the bottom of
232your code for this to work.
233
e606ae5f 234=head2 B<< Moose::Role->init_meta(for_class => $role, metaclass => $metaclass) >>
235
236The C<init_meta> method sets up the metaclass object for the role
237specified by C<for_class>. It also injects a a C<meta> accessor into
238the role so you can get at this object.
239
240The default metaclass is L<Moose::Meta::Role>. You can specify an
241alternate metaclass with the C<metaclass> parameter.
242
c1381000 243=head1 METACLASS
244
245When you use Moose::Role, you can specify which metaclass to use:
246
247 use Moose::Role -metaclass => 'My::Meta::Role';
248
249You can also specify traits which will be applied to your role metaclass:
250
251 use Moose::Role -traits => 'My::Trait';
252
253This is very similar to the attribute traits feature. When you do
254this, your class's C<meta> object will have the specified traits
255applied to it. See L<Moose/TRAIT NAME RESOLUTION> for more details.
256
2c0cbef7 257=head1 CAVEATS
258
85424612 259Role support has only a few caveats:
2c0cbef7 260
261=over 4
76d37e5a 262
76d37e5a 263=item *
264
fb1e11d5 265Roles cannot use the C<extends> keyword; it will throw an exception for now.
266The same is true of the C<augment> and C<inner> keywords (not sure those
267really make sense for roles). All other Moose keywords will be I<deferred>
85424612 268so that they can be applied to the consuming class.
76d37e5a 269
fb1e11d5 270=item *
2c0cbef7 271
85424612 272Role composition does its best to B<not> be order-sensitive when it comes to
273conflict resolution and requirements detection. However, it is order-sensitive
274when it comes to method modifiers. All before/around/after modifiers are
275included whenever a role is composed into a class, and then applied in the order
276in which the roles are used. This also means that there is no conflict for
277before/around/after modifiers.
2c0cbef7 278
85424612 279In most cases, this will be a non-issue; however, it is something to keep in
280mind when using method modifiers in a role. You should never assume any
2c0cbef7 281ordering.
282
e185c027 283=back
284
285=head1 BUGS
286
fb1e11d5 287All complex software has bugs lurking in it, and this module is no
e185c027 288exception. If you find a bug please either email me, or add the bug
289to cpan-RT.
290
291=head1 AUTHOR
292
293Stevan Little E<lt>stevan@iinteractive.comE<gt>
294
db1ab48d 295Christian Hansen E<lt>chansen@cpan.orgE<gt>
98aae381 296
e185c027 297=head1 COPYRIGHT AND LICENSE
298
2840a3b2 299Copyright 2006-2009 by Infinity Interactive, Inc.
e185c027 300
301L<http://www.iinteractive.com>
302
303This library is free software; you can redistribute it and/or modify
fb1e11d5 304it under the same terms as Perl itself.
e185c027 305
68117c45 306=cut