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