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