add release date and bump version
[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
1aab4011 13our $VERSION = '0.64';
e606ae5f 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
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
110my $exporter = Moose::Exporter->setup_import_methods(
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
125 my $role = $args{for_class}
c245d69b 126 or Moose->throw_error("Cannot call init_meta without specifying a for_class");
e606ae5f 127
128 my $metaclass = $args{metaclass} || "Moose::Meta::Role";
129
130 # make a subtype for each Moose class
131 role_type $role unless find_type_constraint($role);
132
133 # FIXME copy from Moose.pm
134 my $meta;
135 if ($role->can('meta')) {
136 $meta = $role->meta();
137 (blessed($meta) && $meta->isa('Moose::Meta::Role'))
c245d69b 138 || Moose->throw_error("You already have a &meta function, but it does not return a Moose::Meta::Role");
e606ae5f 139 }
140 else {
141 $meta = $metaclass->initialize($role);
142
143 $meta->add_method(
144 'meta' => sub {
145 # re-initialize so it inherits properly
146 $metaclass->initialize( ref($_[0]) || $_[0] );
d31f9614 147 }
e606ae5f 148 );
d31f9614 149 }
e606ae5f 150
151 return $meta;
e185c027 152}
153
1541;
155
156__END__
157
158=pod
159
160=head1 NAME
161
162Moose::Role - The Moose Role
163
76d37e5a 164=head1 SYNOPSIS
165
166 package Eq;
85424612 167 use Moose::Role; # automatically turns on strict and warnings
fb1e11d5 168
e46edf94 169 requires 'equal';
fb1e11d5 170
171 sub no_equal {
76d37e5a 172 my ($self, $other) = @_;
173 !$self->equal($other);
174 }
fb1e11d5 175
76d37e5a 176 # ... then in your classes
fb1e11d5 177
76d37e5a 178 package Currency;
85424612 179 use Moose; # automatically turns on strict and warnings
fb1e11d5 180
76d37e5a 181 with 'Eq';
fb1e11d5 182
76d37e5a 183 sub equal {
184 my ($self, $other) = @_;
bdabd620 185 $self->as_float == $other->as_float;
76d37e5a 186 }
187
e185c027 188=head1 DESCRIPTION
189
85424612 190Role support in Moose is pretty solid at this point. However, the best
191documentation is still the the test suite. It is fairly safe to assume Perl 6
192style behavior and then either refer to the test suite, or ask questions on
193#moose if something doesn't quite do what you expect.
d44714be 194
85424612 195We are planning writing some more documentation in the near future, but nothing
196is ready yet, sorry.
76d37e5a 197
2c0cbef7 198=head1 EXPORTED FUNCTIONS
199
85424612 200Moose::Role currently supports all of the functions that L<Moose> exports, but
201differs slightly in how some items are handled (see L<CAVEATS> below for
202details).
76d37e5a 203
85424612 204Moose::Role also offers two role-specific keyword exports:
e185c027 205
206=over 4
207
2c0cbef7 208=item B<requires (@method_names)>
76d37e5a 209
fb1e11d5 210Roles can require that certain methods are implemented by any class which
85424612 211C<does> the role.
9e93dd19 212
2c0cbef7 213=item B<excludes (@role_names)>
214
9e93dd19 215Roles can C<exclude> other roles, in effect saying "I can never be combined
fb1e11d5 216with these C<@role_names>". This is a feature which should not be used
85424612 217lightly.
9e93dd19 218
2c0cbef7 219=back
220
d31f9614 221=head2 B<unimport>
222
223Moose::Role offers a way to remove the keywords it exports, through the
224C<unimport> method. You simply have to say C<no Moose::Role> at the bottom of
225your code for this to work.
226
e606ae5f 227=head2 B<< Moose::Role->init_meta(for_class => $role, metaclass => $metaclass) >>
228
229The C<init_meta> method sets up the metaclass object for the role
230specified by C<for_class>. It also injects a a C<meta> accessor into
231the role so you can get at this object.
232
233The default metaclass is L<Moose::Meta::Role>. You can specify an
234alternate metaclass with the C<metaclass> parameter.
235
2c0cbef7 236=head1 CAVEATS
237
85424612 238Role support has only a few caveats:
2c0cbef7 239
240=over 4
76d37e5a 241
76d37e5a 242=item *
243
fb1e11d5 244Roles cannot use the C<extends> keyword; it will throw an exception for now.
245The same is true of the C<augment> and C<inner> keywords (not sure those
246really make sense for roles). All other Moose keywords will be I<deferred>
85424612 247so that they can be applied to the consuming class.
76d37e5a 248
fb1e11d5 249=item *
2c0cbef7 250
85424612 251Role composition does its best to B<not> be order-sensitive when it comes to
252conflict resolution and requirements detection. However, it is order-sensitive
253when it comes to method modifiers. All before/around/after modifiers are
254included whenever a role is composed into a class, and then applied in the order
255in which the roles are used. This also means that there is no conflict for
256before/around/after modifiers.
2c0cbef7 257
85424612 258In most cases, this will be a non-issue; however, it is something to keep in
259mind when using method modifiers in a role. You should never assume any
2c0cbef7 260ordering.
261
262=item *
263
fb1e11d5 264The C<requires> keyword currently only works with actual methods. A method
265modifier (before/around/after and override) will not count as a fufillment
2c0cbef7 266of the requirement, and neither will an autogenerated accessor for an attribute.
267
85424612 268It is likely that attribute accessors will eventually be allowed to fufill those
269requirements, or we will introduce a C<requires_attr> keyword of some kind
270instead. This decision has not yet been finalized.
2c0cbef7 271
e185c027 272=back
273
274=head1 BUGS
275
fb1e11d5 276All complex software has bugs lurking in it, and this module is no
e185c027 277exception. If you find a bug please either email me, or add the bug
278to cpan-RT.
279
280=head1 AUTHOR
281
282Stevan Little E<lt>stevan@iinteractive.comE<gt>
283
db1ab48d 284Christian Hansen E<lt>chansen@cpan.orgE<gt>
98aae381 285
e185c027 286=head1 COPYRIGHT AND LICENSE
287
778db3ac 288Copyright 2006-2008 by Infinity Interactive, Inc.
e185c027 289
290L<http://www.iinteractive.com>
291
292This library is free software; you can redistribute it and/or modify
fb1e11d5 293it under the same terms as Perl itself.
e185c027 294
68117c45 295=cut