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