bump version to 0.56 and update changes for release
[gitmo/Moose.git] / lib / Moose / Role.pm
CommitLineData
e185c027 1
2package Moose::Role;
3
4use strict;
5use warnings;
6
e65dccbc 7use Scalar::Util 'blessed';
cc5e6b6f 8use Carp 'confess', 'croak';
e185c027 9
c4538447 10use Data::OptList;
2d562421 11use Sub::Exporter;
12
3d24a30e 13our $VERSION = '0.56';
75b95414 14$VERSION = eval $VERSION;
d44714be 15our $AUTHORITY = 'cpan:STEVAN';
e185c027 16
d7d8a8c7 17use Moose ();
18use Moose::Util ();
e65dccbc 19
e185c027 20use Moose::Meta::Role;
7eaef7ad 21use Moose::Util::TypeConstraints;
e185c027 22
5bd4db9b 23sub extends {
24 croak "Roles do not currently support 'extends'";
25}
fb1e11d5 26
5bd4db9b 27sub with {
acbc8892 28 Moose::Util::apply_all_roles( Moose::Meta::Role->initialize(shift), @_ );
5bd4db9b 29}
2d562421 30
5bd4db9b 31sub requires {
acbc8892 32 my $meta = Moose::Meta::Role->initialize(shift);
5bd4db9b 33 croak "Must specify at least one method" unless @_;
34 $meta->add_required_methods(@_);
35}
fb1e11d5 36
5bd4db9b 37sub excludes {
acbc8892 38 my $meta = Moose::Meta::Role->initialize(shift);
5bd4db9b 39 croak "Must specify at least one role" unless @_;
40 $meta->add_excluded_roles(@_);
41}
fc9a40d7 42
5bd4db9b 43sub has {
acbc8892 44 my $meta = Moose::Meta::Role->initialize(shift);
5bd4db9b 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}
fb1e11d5 51
5bd4db9b 52sub before {
acbc8892 53 my $meta = Moose::Meta::Role->initialize(shift);
5bd4db9b 54 my $code = pop @_;
2d562421 55
5bd4db9b 56 for (@_) {
57 croak "Moose::Role do not currently support "
58 . ref($_)
59 . " references for before method modifiers"
60 if ref $_;
61 $meta->add_before_method_modifier( $_, $code );
62 }
63}
64
65sub after {
acbc8892 66 my $meta = Moose::Meta::Role->initialize(shift);
5bd4db9b 67
68 my $code = pop @_;
69 for (@_) {
70 croak "Moose::Role do not currently support "
71 . ref($_)
72 . " references for after method modifiers"
73 if ref $_;
74 $meta->add_after_method_modifier( $_, $code );
75 }
76}
2d562421 77
5bd4db9b 78sub around {
acbc8892 79 my $meta = Moose::Meta::Role->initialize(shift);
5bd4db9b 80 my $code = pop @_;
81 for (@_) {
82 croak "Moose::Role do not currently support "
83 . ref($_)
84 . " references for around method modifiers"
85 if ref $_;
86 $meta->add_around_method_modifier( $_, $code );
87 }
88}
2d562421 89
5bd4db9b 90# see Moose.pm for discussion
91sub super {
92 return unless $Moose::SUPER_BODY;
93 $Moose::SUPER_BODY->(@Moose::SUPER_ARGS);
94}
d31f9614 95
5bd4db9b 96sub override {
acbc8892 97 my $meta = Moose::Meta::Role->initialize(shift);
5bd4db9b 98 my ( $name, $code ) = @_;
99 $meta->add_override_method_modifier( $name, $code );
100}
d31f9614 101
5bd4db9b 102sub inner {
103 croak "Moose::Role cannot support 'inner'";
104}
d31f9614 105
5bd4db9b 106sub augment {
107 croak "Moose::Role cannot support 'augment'";
108}
d31f9614 109
aedcb7d9 110my $exporter = Moose::Exporter->setup_import_methods(
97a93056 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 ),
5bd4db9b 116 \&Carp::confess,
117 \&Scalar::Util::blessed,
118 ],
119);
120
0474f1d0 121sub init_meta {
122 shift;
123 my %args = @_;
cbb03d24 124
0474f1d0 125 my $role = $args{for_class}
126 or confess
127 "Cannot call init_meta without specifying a for_class";
0338a411 128
0474f1d0 129 my $metaclass = $args{metaclass} || "Moose::Meta::Role";
cbb03d24 130
0474f1d0 131 # make a subtype for each Moose class
132 role_type $role unless find_type_constraint($role);
cbb03d24 133
0474f1d0 134 # FIXME copy from Moose.pm
135 my $meta;
136 if ($role->can('meta')) {
137 $meta = $role->meta();
138 (blessed($meta) && $meta->isa('Moose::Meta::Role'))
139 || confess "You already have a &meta function, but it does not return a Moose::Meta::Role";
cbb03d24 140 }
0474f1d0 141 else {
142 $meta = $metaclass->initialize($role);
72d15b83 143
144 $meta->add_method(
145 'meta' => sub {
146 # re-initialize so it inherits properly
147 $metaclass->initialize( ref($_[0]) || $_[0] );
148 }
149 );
0474f1d0 150 }
151
152 return $meta;
cbb03d24 153}
154
e185c027 1551;
156
157__END__
158
159=pod
160
161=head1 NAME
162
163Moose::Role - The Moose Role
164
76d37e5a 165=head1 SYNOPSIS
166
167 package Eq;
85424612 168 use Moose::Role; # automatically turns on strict and warnings
fb1e11d5 169
e46edf94 170 requires 'equal';
fb1e11d5 171
172 sub no_equal {
76d37e5a 173 my ($self, $other) = @_;
174 !$self->equal($other);
175 }
fb1e11d5 176
76d37e5a 177 # ... then in your classes
fb1e11d5 178
76d37e5a 179 package Currency;
85424612 180 use Moose; # automatically turns on strict and warnings
fb1e11d5 181
76d37e5a 182 with 'Eq';
fb1e11d5 183
76d37e5a 184 sub equal {
185 my ($self, $other) = @_;
bdabd620 186 $self->as_float == $other->as_float;
76d37e5a 187 }
188
e185c027 189=head1 DESCRIPTION
190
85424612 191Role support in Moose is pretty solid at this point. However, the best
192documentation is still the the test suite. It is fairly safe to assume Perl 6
193style behavior and then either refer to the test suite, or ask questions on
194#moose if something doesn't quite do what you expect.
d44714be 195
85424612 196We are planning writing some more documentation in the near future, but nothing
197is ready yet, sorry.
76d37e5a 198
2c0cbef7 199=head1 EXPORTED FUNCTIONS
200
85424612 201Moose::Role currently supports all of the functions that L<Moose> exports, but
202differs slightly in how some items are handled (see L<CAVEATS> below for
203details).
76d37e5a 204
85424612 205Moose::Role also offers two role-specific keyword exports:
e185c027 206
207=over 4
208
2c0cbef7 209=item B<requires (@method_names)>
76d37e5a 210
fb1e11d5 211Roles can require that certain methods are implemented by any class which
85424612 212C<does> the role.
9e93dd19 213
2c0cbef7 214=item B<excludes (@role_names)>
215
9e93dd19 216Roles can C<exclude> other roles, in effect saying "I can never be combined
fb1e11d5 217with these C<@role_names>". This is a feature which should not be used
85424612 218lightly.
9e93dd19 219
2c0cbef7 220=back
221
d31f9614 222=head2 B<unimport>
223
224Moose::Role offers a way to remove the keywords it exports, through the
225C<unimport> method. You simply have to say C<no Moose::Role> at the bottom of
226your code for this to work.
227
1ccc7f8a 228=head2 B<< Moose::Role->init_meta(for_class => $role, metaclass => $metaclass) >>
229
230The C<init_meta> method sets up the metaclass object for the role
231specified by C<for_class>. It also injects a a C<meta> accessor into
232the role so you can get at this object.
233
90ef0366 234The default metaclass is L<Moose::Meta::Role>. You can specify an
1ccc7f8a 235alternate metaclass with the C<metaclass> parameter.
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
263=item *
264
fb1e11d5 265The C<requires> keyword currently only works with actual methods. A method
266modifier (before/around/after and override) will not count as a fufillment
2c0cbef7 267of the requirement, and neither will an autogenerated accessor for an attribute.
268
85424612 269It is likely that attribute accessors will eventually be allowed to fufill those
270requirements, or we will introduce a C<requires_attr> keyword of some kind
271instead. This decision has not yet been finalized.
2c0cbef7 272
e185c027 273=back
274
275=head1 BUGS
276
fb1e11d5 277All complex software has bugs lurking in it, and this module is no
e185c027 278exception. If you find a bug please either email me, or add the bug
279to cpan-RT.
280
281=head1 AUTHOR
282
283Stevan Little E<lt>stevan@iinteractive.comE<gt>
284
db1ab48d 285Christian Hansen E<lt>chansen@cpan.orgE<gt>
98aae381 286
e185c027 287=head1 COPYRIGHT AND LICENSE
288
778db3ac 289Copyright 2006-2008 by Infinity Interactive, Inc.
e185c027 290
291L<http://www.iinteractive.com>
292
293This library is free software; you can redistribute it and/or modify
fb1e11d5 294it under the same terms as Perl itself.
e185c027 295
68117c45 296=cut