=head1 NAME
-Moose::Manual::Roles - Roles, an Alternative to Deep Hierarchies and Base Classes
+Moose::Manual::Roles - Roles, an alternative to deep hierarchies and base classes
=head1 WHAT IS A ROLE?
A role is something that classes do. Usually, a role encapsulates some
piece of behavior or state that can be shared between classes. It is
-important to understand that I<roles are not classes>. Roles do not
-participate in inheritance, and a role cannot be instantiated. We
-sometimes say that classes I<consume> roles.
+important to understand that I<roles are not classes>. You cannot
+inherit from a role, and a role cannot be instantiated. We sometimes
+say that roles are I<consumed>, either by classes or other roles.
Instead, a role is I<composed> into a class. In practical terms, this
means that all of the methods and attributes defined in a role are
added directly to (we sometimes say "flattened into") the class that
consumes the role. These attributes and methods then appear as if they
-were defined in the class itself.
+were defined in the class itself. A subclass of the consuming class
+will inherit all of these methods and attributes.
Moose roles are similar to mixins or interfaces in other languages.
methods, in which case the role would be very much like a Java
interface.
+Note that attribute accessors also count as methods for the
+purposes of satisfying the requirements of a role.
+
=head1 A SIMPLE ROLE
Creating a role looks a lot like creating a Moose class:
$self->is_broken(1);
}
-Except for our use of C<Moose::Role>, this looks just like a class
+Except for our use of L<Moose::Role>, this looks just like a class
definition with Moose. However, this is not a class, and it cannot be
instantiated.
}
}
+=head2 Roles Versus Abstract Base Classes
+
+If you are familiar with the concept of abstract base classes in other
+languages, you may be tempted to use roles in the same way.
+
+You I<can> define an "interface-only" role, one that contains I<just>
+a list of required methods.
+
+However, any class which consumes this role must implement all of the
+required methods, either directly or through inheritance from a
+parent. You cannot delay the method requirement check so that they can
+be implemented by future subclasses.
+
+Because the role defines the required methods directly, adding a base
+class to the mix would not achieve anything. We recommend that you
+simply consume the interface role in each class which implements that
+interface.
+
+=head2 Required Attributes
+
+As mentioned before, a role requirement may also be satisfied by an
+attribute accessor. But any C<has> functions, which will generate
+accessors that satisfy the role requirement, must be placed
+I<before> the C<with> function that composes the role.
+
+ package Breakable;
+
+ use Moose::Role;
+
+ requires 'stress';
+
+ package Car;
+
+ use Moose;
+
+ has 'stress' => (
+ is => 'rw',
+ isa => 'Int',
+ );
+
+ with 'Breakable';
+
=head1 USING METHOD MODIFIERS
Method modifiers and roles are a very powerful combination. Often, a
the same name, we will have a conflict. In that case, the composing
class is required to provide its I<own> method of the same name.
- package Breakdances;
+ package Breakdancer;
use Moose::Role
use Moose;
- with 'Breakable' => { alias => { break => 'break_bone' } },
- 'Breakdancer' => { alias => { break => 'break_dance' } };
+ with 'Breakable' => { -alias => { break => 'break_bone' } },
+ 'Breakdancer' => { -alias => { break => 'break_dance' } };
However, aliasing a method simply makes a I<copy> of the method with
the new name. We also need to exclude the original name:
with 'Breakable' => {
- alias => { break => 'break_bone' },
- exclude => 'break',
+ -alias => { break => 'break_bone' },
+ -excludes => 'break',
},
'Breakdancer' => {
- alias => { break => 'break_dance' },
- exclude => 'break',
+ -alias => { break => 'break_dance' },
+ -excludes => 'break',
};
-The exclude parameter prevents the C<break> method from being composed
+The excludes parameter prevents the C<break> method from being composed
into the C<FragileDancer> class, so we don't have a conflict. This
means that C<FragileDancer> does not need to implement its own
C<break> method.