summaryrefslogtreecommitdiff
path: root/lib/Moose/Manual/Roles.pod
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Moose/Manual/Roles.pod')
-rw-r--r--lib/Moose/Manual/Roles.pod422
1 files changed, 422 insertions, 0 deletions
diff --git a/lib/Moose/Manual/Roles.pod b/lib/Moose/Manual/Roles.pod
new file mode 100644
index 0000000..3000e39
--- /dev/null
+++ b/lib/Moose/Manual/Roles.pod
@@ -0,0 +1,422 @@
+# PODNAME: Moose::Manual::Roles
+# ABSTRACT: Roles, an alternative to deep hierarchies and base classes
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Moose::Manual::Roles - Roles, an alternative to deep hierarchies and base classes
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 WHAT IS A ROLE?
+
+A role encapsulates some piece of behavior or state that can be shared between
+classes. It is something that classes I<do>. It is 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, method modifiers, 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. 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.
+
+Besides defining their own methods and attributes, roles can also
+require that the consuming class define certain methods of its
+own. You could have a role that consisted only of a list of required
+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:
+
+ package Breakable;
+
+ use Moose::Role;
+
+ has 'is_broken' => (
+ is => 'rw',
+ isa => 'Bool',
+ );
+
+ sub break {
+ my $self = shift;
+
+ print "I broke\n";
+
+ $self->is_broken(1);
+ }
+
+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.
+
+Instead, its attributes and methods will be composed into classes
+which use the role:
+
+ package Car;
+
+ use Moose;
+
+ with 'Breakable';
+
+ has 'engine' => (
+ is => 'ro',
+ isa => 'Engine',
+ );
+
+The C<with> function composes roles into a class. Once that is done,
+the C<Car> class has an C<is_broken> attribute and a C<break>
+method. The C<Car> class also C<does('Breakable')>:
+
+ my $car = Car->new( engine => Engine->new );
+
+ print $car->is_broken ? 'Busted' : 'Still working';
+ $car->break;
+ print $car->is_broken ? 'Busted' : 'Still working';
+
+ $car->does('Breakable'); # true
+
+This prints:
+
+ Still working
+ I broke
+ Busted
+
+We could use this same role in a C<Bone> class:
+
+ package Bone;
+
+ use Moose;
+
+ with 'Breakable';
+
+ has 'marrow' => (
+ is => 'ro',
+ isa => 'Marrow',
+ );
+
+See also L<Moose::Cookbook::Roles::Comparable_CodeReuse> for an example.
+
+It's possible to compose existing roles into new roles. For example, we can
+have a C<HandleWithCare> class which applies both the C<Breakable> and
+C<Package> roles to any class which consumes it:
+
+ package HandleWithCare;
+
+ use Moose::Role;
+
+ with 'Breakable', 'Package';
+
+=head1 REQUIRED METHODS
+
+As mentioned previously, a role can require that consuming classes
+provide one or more methods. Using our C<Breakable> example, let's
+make it require that consuming classes implement their own C<break>
+methods:
+
+ package Breakable;
+
+ use Moose::Role;
+
+ requires 'break';
+
+ has 'is_broken' => (
+ is => 'rw',
+ isa => 'Bool',
+ );
+
+ after 'break' => sub {
+ my $self = shift;
+
+ $self->is_broken(1);
+ };
+
+If we try to consume this role in a class that does not have a
+C<break> method, we will get an exception.
+
+You can see that we added a method modifier on C<break>. We want
+classes that consume this role to implement their own logic for
+breaking, but we make sure that the C<is_broken> attribute is always
+set to true when C<break> is called.
+
+ package Car
+
+ use Moose;
+
+ with 'Breakable';
+
+ has 'engine' => (
+ is => 'ro',
+ isa => 'Engine',
+ );
+
+ sub break {
+ my $self = shift;
+
+ if ( $self->is_moving ) {
+ $self->stop;
+ }
+ }
+
+=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's required method may also be satisfied by an
+attribute accessor. However, the call to C<has> which defines an attribute
+happens at runtime. This means that you must define the attribute I<before>
+consuming the role, or else the role will not see the generated accessor.
+
+ 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
+role will combine method modifiers and required methods. We already
+saw one example with our C<Breakable> example.
+
+Method modifiers increase the complexity of roles, because they make
+the role application order relevant. If a class uses multiple roles,
+each of which modify the same method, those modifiers will be applied
+in the same order as the roles are used:
+
+ package MovieCar;
+
+ use Moose;
+
+ extends 'Car';
+
+ with 'Breakable', 'ExplodesOnBreakage';
+
+Assuming that the new C<ExplodesOnBreakage> role I<also> has an
+C<after> modifier on C<break>, the C<after> modifiers will run one
+after the other. The modifier from C<Breakable> will run first, then
+the one from C<ExplodesOnBreakage>.
+
+=head1 METHOD CONFLICTS
+
+If a class composes multiple roles, and those roles have methods of
+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 Breakdancer;
+
+ use Moose::Role;
+
+ sub break {
+
+ }
+
+If we compose both C<Breakable> and C<Breakdancer> in a class, we must
+provide our own C<break> method:
+
+ package FragileDancer;
+
+ use Moose;
+
+ with 'Breakable', 'Breakdancer';
+
+ sub break { ... }
+
+A role can be a collection of other roles:
+
+ package Break::Bundle;
+
+ use Moose::Role;
+
+ with ('Breakable', 'Breakdancer');
+
+When a role consumes another a role, the I<consuming> role's methods silently
+win in any conflict, and the consumed role's methods are simply ignored.
+
+=head1 METHOD EXCLUSION AND ALIASING
+
+If we want our C<FragileDancer> class to be able to call the methods
+from both its roles, we can alias the methods:
+
+ package FragileDancer;
+
+ use Moose;
+
+ 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' },
+ -excludes => 'break',
+ },
+ 'Breakdancer' => {
+ -alias => { break => 'break_dance' },
+ -excludes => 'break',
+ };
+
+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.
+
+This is useful, but it's worth noting that this breaks the contract
+implicit in consuming a role. Our C<FragileDancer> class does both the
+C<Breakable> and C<BreakDancer>, but does not provide a C<break>
+method. If some API expects an object that does one of those roles, it
+probably expects it to implement that method.
+
+In some use cases we might alias and exclude methods from roles, but
+then provide a method of the same name in the class itself.
+
+Also see L<Moose::Cookbook::Roles::Restartable_AdvancedComposition> for an example.
+
+=head1 OVERLOADING
+
+When a Moose role uses overloading, that overloading is composed into any
+classes that consume the role. This includes the setting of the C<fallback>
+value for that role's overloading. Just as with methods and attributes, when a
+role consumes another role, that other role's overloading settings are applied
+to the role.
+
+Just as with methods, there can be conflicts with overloading implementations
+between multiple roles when they are all consumed by a class. If two roles
+both provide different overloading implementations for a given operator, that
+is a conflict. If two roles both implement overloading and have different
+C<fallback> values, that is also considered a conflict. These conflicts are
+detected when multiple roles are being composed into a class together.
+
+When a role consumes another role, the consuming role's overloading fallback
+and operator implementations silently "win" the conflict.
+
+=head1 ROLE EXCLUSION
+
+A role can say that it cannot be combined with some other role. This
+should be used with great caution, since it limits the re-usability of
+the role.
+
+ package Breakable;
+
+ use Moose::Role;
+
+ excludes 'BreakDancer';
+
+=head1 ADDING A ROLE TO AN OBJECT INSTANCE
+
+You may want to add a role to an object instance, rather than to a class. For
+example, you may want to add debug tracing to one instance of an object while
+debugging a particular bug. Another use case might be to dynamically change
+objects based on a user's configuration, as a plugin system.
+
+The best way to do this is to use the C<apply_all_roles()> function from
+L<Moose::Util>:
+
+ use Moose::Util qw( apply_all_roles );
+
+ my $car = Car->new;
+ apply_all_roles( $car, 'Breakable' );
+
+This function can apply more than one role at a time, and will do so using the
+normal Moose role combination system. We recommend using this function to
+apply roles to an object. This is what Moose uses internally when you call
+C<with>.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut