Checking in changes prior to tagging of version 0.84.
[gitmo/Mouse.git] / lib / Mouse / Role.pm
1 package Mouse::Role;
2 use Mouse::Exporter; # enables strict and warnings
3
4 our $VERSION = '0.84';
5
6 use Carp         qw(confess);
7 use Scalar::Util qw(blessed);
8
9 use Mouse ();
10
11 Mouse::Exporter->setup_import_methods(
12     as_is => [qw(
13         extends with
14         has
15         before after around
16         override super
17         augment  inner
18
19         requires excludes
20     ),
21         \&Scalar::Util::blessed,
22         \&Carp::confess,
23     ],
24 );
25
26
27 sub extends  {
28     Carp::croak "Roles do not support 'extends'";
29 }
30
31 sub with {
32     Mouse::Util::apply_all_roles(scalar(caller), @_);
33     return;
34 }
35
36 sub has {
37     my $meta = Mouse::Meta::Role->initialize(scalar caller);
38     my $name = shift;
39
40     $meta->throw_error(q{Usage: has 'name' => ( key => value, ... )})
41         if @_ % 2; # odd number of arguments
42
43     for my $n(ref($name) ? @{$name} : $name){
44         $meta->add_attribute($n => @_);
45     }
46     return;
47 }
48
49 sub before {
50     my $meta = Mouse::Meta::Role->initialize(scalar caller);
51     my $code = pop;
52     for my $name($meta->_collect_methods(@_)) {
53         $meta->add_before_method_modifier($name => $code);
54     }
55     return;
56 }
57
58 sub after {
59     my $meta = Mouse::Meta::Role->initialize(scalar caller);
60     my $code = pop;
61     for my $name($meta->_collect_methods(@_)) {
62         $meta->add_after_method_modifier($name => $code);
63     }
64     return;
65 }
66
67 sub around {
68     my $meta = Mouse::Meta::Role->initialize(scalar caller);
69     my $code = pop;
70     for my $name($meta->_collect_methods(@_)) {
71         $meta->add_around_method_modifier($name => $code);
72     }
73     return;
74 }
75
76
77 sub super {
78     return if !defined $Mouse::SUPER_BODY;
79     $Mouse::SUPER_BODY->(@Mouse::SUPER_ARGS);
80 }
81
82 sub override {
83     # my($name, $code) = @_;
84     Mouse::Meta::Role->initialize(scalar caller)->add_override_method_modifier(@_);
85     return;
86 }
87
88 # We keep the same errors messages as Moose::Role emits, here.
89 sub inner {
90     Carp::croak "Roles cannot support 'inner'";
91 }
92
93 sub augment {
94     Carp::croak "Roles cannot support 'augment'";
95 }
96
97 sub requires {
98     my $meta = Mouse::Meta::Role->initialize(scalar caller);
99     $meta->throw_error("Must specify at least one method") unless @_;
100     $meta->add_required_methods(@_);
101     return;
102 }
103
104 sub excludes {
105     Mouse::Util::not_supported();
106 }
107
108 sub init_meta{
109     shift;
110     my %args = @_;
111
112     my $class = $args{for_class}
113         or Carp::confess("Cannot call init_meta without specifying a for_class");
114
115     my $metaclass  = $args{metaclass}  || 'Mouse::Meta::Role';
116
117     my $meta = $metaclass->initialize($class);
118
119     $meta->add_method(meta => sub{
120         $metaclass->initialize(ref($_[0]) || $_[0]);
121     });
122
123     # make a role type for each Mouse role
124     Mouse::Util::TypeConstraints::role_type($class)
125         unless Mouse::Util::TypeConstraints::find_type_constraint($class);
126
127     return $meta;
128 }
129
130 1;
131
132 __END__
133
134 =head1 NAME
135
136 Mouse::Role - The Mouse Role
137
138 =head1 VERSION
139
140 This document describes Mouse version 0.84
141
142 =head1 SYNOPSIS
143
144     package Comparable;
145     use Mouse::Role; # the package is now a Mouse role
146
147     # Declare methods that are required by this role
148     requires qw(compare);
149
150     # Define methods this role provides
151     sub equals {
152         my($self, $other) = @_;
153         return $self->compare($other) == 0;
154     }
155
156     # and later
157     package MyObject;
158     use Mouse;
159     with qw(Comparable); # Now MyObject can equals()
160
161     sub compare {
162         # ...
163     }
164
165     my $foo = MyObject->new();
166     my $bar = MyObject->new();
167     $obj->equals($bar); # yes, it is comparable
168
169 =head1 KEYWORDS
170
171 =head2 C<< meta -> Mouse::Meta::Role >>
172
173 Returns this role's metaclass instance.
174
175 =head2 C<< before (method|methods|regexp) -> CodeRef >>
176
177 Sets up a B<before> method modifier. See L<Moose/before>.
178
179 =head2 C<< after (method|methods|regexp) => CodeRef >>
180
181 Sets up an B<after> method modifier. See L<Moose/after>.
182
183 =head2 C<< around (method|methods|regexp) => CodeRef >>
184
185 Sets up an B<around> method modifier. See L<Moose/around>.
186
187 =head2 C<super>
188
189 Sets up the B<super> keyword. See L<Moose/super>.
190
191 =head2  C<< override method => CodeRef >>
192
193 Sets up an B<override> method modifier. See L<Moose/Role/override>.
194
195 =head2 C<inner>
196
197 This is not supported in roles and emits an error. See L<Moose/Role>.
198
199 =head2 C<< augment method => CodeRef >>
200
201 This is not supported in roles and emits an error. See L<Moose/Role>.
202
203 =head2 C<< has (name|names) => parameters >>
204
205 Sets up an attribute (or if passed an arrayref of names, multiple attributes) to
206 this role. See L<Mouse/has>.
207
208 =head2 C<< confess(error) -> BOOM >>
209
210 L<Carp/confess> for your convenience.
211
212 =head2 C<< blessed(value) -> ClassName | undef >>
213
214 L<Scalar::Util/blessed> for your convenience.
215
216 =head1 MISC
217
218 =head2 import
219
220 Importing Mouse::Role will give you sugar.
221
222 =head2 unimport
223
224 Please unimport (C<< no Mouse::Role >>) so that if someone calls one of the
225 keywords (such as L</has>) it will break loudly instead breaking subtly.
226
227 =head1 SEE ALSO
228
229 L<Moose::Role>
230
231 =cut
232