Removed __CURRY_EXPORTS_FOR_CLASS__
[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 {
27 Moose::Util::apply_all_roles( shift->meta(), @_ );
28}
2d562421 29
5bd4db9b 30sub requires {
31 my $meta = shift->meta();
32 croak "Must specify at least one method" unless @_;
33 $meta->add_required_methods(@_);
34}
fb1e11d5 35
5bd4db9b 36sub excludes {
37 my $meta = shift->meta();
38 croak "Must specify at least one role" unless @_;
39 $meta->add_excluded_roles(@_);
40}
fc9a40d7 41
5bd4db9b 42sub has {
43 my $meta = shift->meta();
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 {
52 my $meta = shift->meta();
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 {
65 my $meta = shift->meta();
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 {
78 my $meta = shift->meta();
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 {
96 my $meta = shift->meta();
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
a5c426fc 109my $exporter = Moose::Exporter->build_import_methods(
5bd4db9b 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 ),
115 \&Carp::confess,
116 \&Scalar::Util::blessed,
117 ],
118);
119
cbb03d24 120{
121 my %METAS;
122
0338a411 123 sub _init_meta {
124 shift;
125 my %args = @_;
126
127 my $role = $args{for_class}
128 or confess
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
2c0cbef7 224=head1 CAVEATS
225
85424612 226Role support has only a few caveats:
2c0cbef7 227
228=over 4
76d37e5a 229
76d37e5a 230=item *
231
fb1e11d5 232Roles cannot use the C<extends> keyword; it will throw an exception for now.
233The same is true of the C<augment> and C<inner> keywords (not sure those
234really make sense for roles). All other Moose keywords will be I<deferred>
85424612 235so that they can be applied to the consuming class.
76d37e5a 236
fb1e11d5 237=item *
2c0cbef7 238
85424612 239Role composition does its best to B<not> be order-sensitive when it comes to
240conflict resolution and requirements detection. However, it is order-sensitive
241when it comes to method modifiers. All before/around/after modifiers are
242included whenever a role is composed into a class, and then applied in the order
243in which the roles are used. This also means that there is no conflict for
244before/around/after modifiers.
2c0cbef7 245
85424612 246In most cases, this will be a non-issue; however, it is something to keep in
247mind when using method modifiers in a role. You should never assume any
2c0cbef7 248ordering.
249
250=item *
251
fb1e11d5 252The C<requires> keyword currently only works with actual methods. A method
253modifier (before/around/after and override) will not count as a fufillment
2c0cbef7 254of the requirement, and neither will an autogenerated accessor for an attribute.
255
85424612 256It is likely that attribute accessors will eventually be allowed to fufill those
257requirements, or we will introduce a C<requires_attr> keyword of some kind
258instead. This decision has not yet been finalized.
2c0cbef7 259
e185c027 260=back
261
262=head1 BUGS
263
fb1e11d5 264All complex software has bugs lurking in it, and this module is no
e185c027 265exception. If you find a bug please either email me, or add the bug
266to cpan-RT.
267
268=head1 AUTHOR
269
270Stevan Little E<lt>stevan@iinteractive.comE<gt>
271
db1ab48d 272Christian Hansen E<lt>chansen@cpan.orgE<gt>
98aae381 273
e185c027 274=head1 COPYRIGHT AND LICENSE
275
778db3ac 276Copyright 2006-2008 by Infinity Interactive, Inc.
e185c027 277
278L<http://www.iinteractive.com>
279
280This library is free software; you can redistribute it and/or modify
fb1e11d5 281it under the same terms as Perl itself.
e185c027 282
68117c45 283=cut