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