1package Mouse::Role;
2use Mouse::Exporter; # enables strict and warnings
3
4use version; our $VERSION = version->declare('v2.5.10');
5
6use Carp         ();
7use Scalar::Util ();
8
9use Mouse ();
10
11Mouse::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
27sub extends  {
28    Carp::croak "Roles do not support 'extends'";
29}
30
31sub with {
32    Mouse::Util::apply_all_roles(scalar(caller), @_);
33    return;
34}
35
36sub 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
49sub 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
58sub 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
67sub 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
77sub super {
78    return if !defined $Mouse::SUPER_BODY;
79    $Mouse::SUPER_BODY->(@Mouse::SUPER_ARGS);
80}
81
82sub 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.
89sub inner {
90    Carp::croak "Roles cannot support 'inner'";
91}
92
93sub augment {
94    Carp::croak "Roles cannot support 'augment'";
95}
96
97sub 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
104sub excludes {
105    Mouse::Util::not_supported();
106}
107
108sub 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    my $filename = Mouse::Util::module_notional_filename($meta->name);
119    $INC{$filename} = '(set by Mouse)'
120        unless exists $INC{$filename};
121
122    $meta->add_method(meta => sub{
123        $metaclass->initialize(ref($_[0]) || $_[0]);
124    });
125
126    # make a role type for each Mouse role
127    Mouse::Util::TypeConstraints::role_type($class)
128        unless Mouse::Util::TypeConstraints::find_type_constraint($class);
129
130    return $meta;
131}
132
1331;
134
135__END__
136
137=head1 NAME
138
139Mouse::Role - The Mouse Role
140
141=head1 VERSION
142
143This document describes Mouse version v2.5.10
144
145=head1 SYNOPSIS
146
147    package Comparable;
148    use Mouse::Role; # the package is now a Mouse role
149
150    # Declare methods that are required by this role
151    requires qw(compare);
152
153    # Define methods this role provides
154    sub equals {
155        my($self, $other) = @_;
156        return $self->compare($other) == 0;
157    }
158
159    # and later
160    package MyObject;
161    use Mouse;
162    with qw(Comparable); # Now MyObject can equals()
163
164    sub compare {
165        # ...
166    }
167
168    my $foo = MyObject->new();
169    my $bar = MyObject->new();
170    $obj->equals($bar); # yes, it is comparable
171
172=head1 DESCRIPTION
173
174This module declares the caller class to be a Mouse role.
175
176The concept of roles is documented in L<Moose::Manual::Roles>.
177This document serves as API documentation.
178
179=head1 EXPORTED FUNCTIONS
180
181Mouse::Role supports all of the functions that Mouse exports, but
182differs slightly in how some items are handled (see L</CAVEATS> below
183for details).
184
185Mouse::Role also offers two role-specific keywords:
186
187=head2 C<< requires(@method_names) >>
188
189Roles can require that certain methods are implemented by any class which
190C<does> the role.
191
192Note that attribute accessors also count as methods for the purposes of
193satisfying the requirements of a role.
194
195=head2 C<< excludes(@role_names) >>
196
197This is exported but not implemented in Mouse.
198
199=head1 IMPORT AND UNIMPORT
200
201=head2 import
202
203Importing Mouse::Role will give you sugar. C<-traits> are also supported.
204
205=head2 unimport
206
207Please unimport (C<< no Mouse::Role >>) so that if someone calls one of the
208keywords (such as L</has>) it will break loudly instead breaking subtly.
209
210=head1 CAVEATS
211
212Role support has only a few caveats:
213
214=over
215
216=item *
217
218Roles cannot use the C<extends> keyword; it will throw an exception for now.
219The same is true of the C<augment> and C<inner> keywords (not sure those
220really make sense for roles). All other Mouse keywords will be I<deferred>
221so that they can be applied to the consuming class.
222
223=item *
224
225Role composition does its best to B<not> be order-sensitive when it comes to
226conflict resolution and requirements detection. However, it is order-sensitive
227when it comes to method modifiers. All before/around/after modifiers are
228included whenever a role is composed into a class, and then applied in the order
229in which the roles are used. This also means that there is no conflict for
230before/around/after modifiers.
231
232In most cases, this will be a non-issue; however, it is something to keep in
233mind when using method modifiers in a role. You should never assume any
234ordering.
235
236=back
237
238=head1 SEE ALSO
239
240L<Mouse>
241
242L<Moose::Role>
243
244L<Moose::Manual::Roles>
245
246L<Moose::Spec::Role>
247
248=cut
249
250