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