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