Link to MX::Types here
[gitmo/Moose.git] / lib / Moose / Role.pm
CommitLineData
e185c027 1
2package Moose::Role;
3
4use strict;
5use warnings;
6
e65dccbc 7use Scalar::Util 'blessed';
f4f808de 8use Carp 'croak';
e185c027 9
c4538447 10use Data::OptList;
2d562421 11use Sub::Exporter;
12
722c9bcb 13our $VERSION = '0.71';
e606ae5f 14$VERSION = eval $VERSION;
d44714be 15our $AUTHORITY = 'cpan:STEVAN';
e185c027 16
d7d8a8c7 17use Moose ();
18use Moose::Util ();
e65dccbc 19
c36b393c 20use Moose::Exporter;
e185c027 21use Moose::Meta::Role;
7eaef7ad 22use Moose::Util::TypeConstraints;
e185c027 23
e606ae5f 24sub extends {
25 croak "Roles do not currently support 'extends'";
26}
27
28sub with {
29 Moose::Util::apply_all_roles( Moose::Meta::Role->initialize(shift), @_ );
30}
31
32sub requires {
33 my $meta = Moose::Meta::Role->initialize(shift);
34 croak "Must specify at least one method" unless @_;
35 $meta->add_required_methods(@_);
36}
37
38sub excludes {
39 my $meta = Moose::Meta::Role->initialize(shift);
40 croak "Must specify at least one role" unless @_;
41 $meta->add_excluded_roles(@_);
42}
2d562421 43
e606ae5f 44sub has {
45 my $meta = Moose::Meta::Role->initialize(shift);
46 my $name = shift;
47 croak 'Usage: has \'name\' => ( key => value, ... )' if @_ == 1;
48 my %options = @_;
49 my $attrs = ( ref($name) eq 'ARRAY' ) ? $name : [ ($name) ];
50 $meta->add_attribute( $_, %options ) for @$attrs;
51}
2d562421 52
e606ae5f 53sub before {
54 my $meta = Moose::Meta::Role->initialize(shift);
55 my $code = pop @_;
fb1e11d5 56
e606ae5f 57 for (@_) {
b8945921 58 croak "Roles do not currently support "
e606ae5f 59 . ref($_)
60 . " references for before method modifiers"
61 if ref $_;
62 $meta->add_before_method_modifier( $_, $code );
63 }
64}
2d562421 65
e606ae5f 66sub after {
67 my $meta = Moose::Meta::Role->initialize(shift);
2d562421 68
e606ae5f 69 my $code = pop @_;
70 for (@_) {
b8945921 71 croak "Roles do not currently support "
e606ae5f 72 . ref($_)
73 . " references for after method modifiers"
74 if ref $_;
75 $meta->add_after_method_modifier( $_, $code );
2d562421 76 }
e606ae5f 77}
fb1e11d5 78
e606ae5f 79sub around {
80 my $meta = Moose::Meta::Role->initialize(shift);
81 my $code = pop @_;
82 for (@_) {
b8945921 83 croak "Roles do not currently support "
e606ae5f 84 . ref($_)
85 . " references for around method modifiers"
86 if ref $_;
87 $meta->add_around_method_modifier( $_, $code );
88 }
89}
fb1e11d5 90
e606ae5f 91# see Moose.pm for discussion
92sub super {
93 return unless $Moose::SUPER_BODY;
94 $Moose::SUPER_BODY->(@Moose::SUPER_ARGS);
95}
96
97sub override {
98 my $meta = Moose::Meta::Role->initialize(shift);
99 my ( $name, $code ) = @_;
100 $meta->add_override_method_modifier( $name, $code );
101}
102
103sub inner {
b8945921 104 croak "Roles cannot support 'inner'";
e606ae5f 105}
106
107sub augment {
b8945921 108 croak "Roles cannot support 'augment'";
e606ae5f 109}
110
c36b393c 111Moose::Exporter->setup_import_methods(
e606ae5f 112 with_caller => [
113 qw( with requires excludes has before after around override make_immutable )
114 ],
115 as_is => [
116 qw( extends super inner augment ),
117 \&Carp::confess,
118 \&Scalar::Util::blessed,
119 ],
120);
121
122sub init_meta {
123 shift;
124 my %args = @_;
125
126 my $role = $args{for_class}
c245d69b 127 or Moose->throw_error("Cannot call init_meta without specifying a for_class");
e606ae5f 128
129 my $metaclass = $args{metaclass} || "Moose::Meta::Role";
130
131 # make a subtype for each Moose class
132 role_type $role unless find_type_constraint($role);
133
134 # FIXME copy from Moose.pm
135 my $meta;
136 if ($role->can('meta')) {
137 $meta = $role->meta();
138 (blessed($meta) && $meta->isa('Moose::Meta::Role'))
c245d69b 139 || Moose->throw_error("You already have a &meta function, but it does not return a Moose::Meta::Role");
e606ae5f 140 }
141 else {
142 $meta = $metaclass->initialize($role);
143
144 $meta->add_method(
145 'meta' => sub {
146 # re-initialize so it inherits properly
147 $metaclass->initialize( ref($_[0]) || $_[0] );
d31f9614 148 }
e606ae5f 149 );
d31f9614 150 }
e606ae5f 151
152 return $meta;
e185c027 153}
154
1551;
156
157__END__
158
159=pod
160
161=head1 NAME
162
163Moose::Role - The Moose Role
164
76d37e5a 165=head1 SYNOPSIS
166
167 package Eq;
85424612 168 use Moose::Role; # automatically turns on strict and warnings
fb1e11d5 169
e46edf94 170 requires 'equal';
fb1e11d5 171
172 sub no_equal {
76d37e5a 173 my ($self, $other) = @_;
174 !$self->equal($other);
175 }
fb1e11d5 176
76d37e5a 177 # ... then in your classes
fb1e11d5 178
76d37e5a 179 package Currency;
85424612 180 use Moose; # automatically turns on strict and warnings
fb1e11d5 181
76d37e5a 182 with 'Eq';
fb1e11d5 183
76d37e5a 184 sub equal {
185 my ($self, $other) = @_;
bdabd620 186 $self->as_float == $other->as_float;
76d37e5a 187 }
188
e185c027 189=head1 DESCRIPTION
190
85424612 191Role support in Moose is pretty solid at this point. However, the best
192documentation is still the the test suite. It is fairly safe to assume Perl 6
193style behavior and then either refer to the test suite, or ask questions on
194#moose if something doesn't quite do what you expect.
d44714be 195
85424612 196We are planning writing some more documentation in the near future, but nothing
197is ready yet, sorry.
76d37e5a 198
2c0cbef7 199=head1 EXPORTED FUNCTIONS
200
85424612 201Moose::Role currently supports all of the functions that L<Moose> exports, but
202differs slightly in how some items are handled (see L<CAVEATS> below for
203details).
76d37e5a 204
85424612 205Moose::Role also offers two role-specific keyword exports:
e185c027 206
207=over 4
208
2c0cbef7 209=item B<requires (@method_names)>
76d37e5a 210
fb1e11d5 211Roles can require that certain methods are implemented by any class which
85424612 212C<does> the role.
9e93dd19 213
2c0cbef7 214=item B<excludes (@role_names)>
215
9e93dd19 216Roles can C<exclude> other roles, in effect saying "I can never be combined
fb1e11d5 217with these C<@role_names>". This is a feature which should not be used
85424612 218lightly.
9e93dd19 219
2c0cbef7 220=back
221
d31f9614 222=head2 B<unimport>
223
224Moose::Role offers a way to remove the keywords it exports, through the
225C<unimport> method. You simply have to say C<no Moose::Role> at the bottom of
226your code for this to work.
227
e606ae5f 228=head2 B<< Moose::Role->init_meta(for_class => $role, metaclass => $metaclass) >>
229
230The C<init_meta> method sets up the metaclass object for the role
231specified by C<for_class>. It also injects a a C<meta> accessor into
232the role so you can get at this object.
233
234The default metaclass is L<Moose::Meta::Role>. You can specify an
235alternate metaclass with the C<metaclass> parameter.
236
2c0cbef7 237=head1 CAVEATS
238
85424612 239Role support has only a few caveats:
2c0cbef7 240
241=over 4
76d37e5a 242
76d37e5a 243=item *
244
fb1e11d5 245Roles cannot use the C<extends> keyword; it will throw an exception for now.
246The same is true of the C<augment> and C<inner> keywords (not sure those
247really make sense for roles). All other Moose keywords will be I<deferred>
85424612 248so that they can be applied to the consuming class.
76d37e5a 249
fb1e11d5 250=item *
2c0cbef7 251
85424612 252Role composition does its best to B<not> be order-sensitive when it comes to
253conflict resolution and requirements detection. However, it is order-sensitive
254when it comes to method modifiers. All before/around/after modifiers are
255included whenever a role is composed into a class, and then applied in the order
256in which the roles are used. This also means that there is no conflict for
257before/around/after modifiers.
2c0cbef7 258
85424612 259In most cases, this will be a non-issue; however, it is something to keep in
260mind when using method modifiers in a role. You should never assume any
2c0cbef7 261ordering.
262
263=item *
264
e62b7a82 265The C<requires> keyword currently only works with actual methods. A
266method modifier (before/around/after and override) will not count as a
267fulfillment of the requirement.
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
2840a3b2 285Copyright 2006-2009 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