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