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