Document how to pass new attribute values at instance-role application time
[gitmo/Moose.git] / lib / Moose / Manual / Roles.pod
index 1745cdc..009a2ea 100644 (file)
@@ -1,22 +1,25 @@
-=pod
+package Moose::Manual::Roles;
+
+# ABSTRACT: Roles, an alternative to deep hierarchies and base classes
 
-=head1 NAME
+__END__
 
-Moose::Manual::Roles - Roles, an Alternative to Deep Hierarchies and Base Classes
+=pod
 
 =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.
+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 and attributes defined in a role are
+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.
+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.
 
@@ -26,6 +29,9 @@ 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:
@@ -47,7 +53,7 @@ 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.
 
@@ -71,9 +77,9 @@ method. The C<Car> class also C<does('Breakable')>:
 
   my $car = Car->new( engine => Engine->new );
 
-  print $car->is_broken ? 'Still working' : 'Busted';
+  print $car->is_broken ? 'Busted' : 'Still working';
   $car->break;
-  print $car->is_broken ? 'Still working' : 'Busted';
+  print $car->is_broken ? 'Busted' : 'Still working';
 
   $car->does('Breakable'); # true
 
@@ -96,6 +102,8 @@ We could use this same role in a C<Bone> class:
       isa => 'Marrow',
   );
 
+See also L<Moose::Cookbook::Roles::Comparable_CodeReuse> for an example.
+
 =head1 REQUIRED METHODS
 
 As mentioned previously, a role can require that consuming classes
@@ -147,6 +155,48 @@ set to true when C<break> is called.
       }
   }
 
+=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
@@ -166,7 +216,7 @@ in the same order as the roles are used:
 
   with 'Breakable', 'ExplodesOnBreakage';
 
-Assuming that the new C<ExplodesOnBreakage> method I<also> has an
+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>.
@@ -177,7 +227,7 @@ 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 Breakdances;
+  package Breakdancer;
 
   use Moose::Role
 
@@ -196,6 +246,14 @@ provide our own C<break> method:
 
   sub break { ... }
 
+A role can be a collection of other roles:
+
+  package Break::Bundle;
+
+  use Moose::Role;
+
+  with ('Breakable', 'Breakdancer');
+
 =head1 METHOD EXCLUSION AND ALIASING
 
 If we want our C<FragileDancer> class to be able to call the methods
@@ -205,22 +263,22 @@ from both its roles, we can alias the methods:
 
   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.
@@ -234,6 +292,8 @@ 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 ROLE EXCLUSION
 
 A role can say that it cannot be combined with some other role. This
@@ -246,17 +306,65 @@ the role.
 
   excludes 'BreakDancer';
 
-=head1 AUTHOR
+=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>.
+
+=head2 Handling required attributes for roles.
+
+Application of some roles will require additional parameters being specified to
+satisfy them, for example:
+
+    {
+        package Car;
+        use Moose;
+    }
+    {
+        package Breakable;
+        use Moose::Role;
+
+        has 'breakable_parts' => ( is => 'ro', required => 1 );
+    }
+
+    my $car = Car->new;
+
+    # next line dies with: Attribute (breakable_parts) is required
+    apply_all_roles( $car, 'Breakable' );
 
-Dave Rolsky E<lt>autarch@urth.orgE<gt>
+This will require passing the additional parameters at application time as
+follows:
 
-=head1 COPYRIGHT AND LICENSE
+    apply_all_roles( $car, 'Breakable' => {
+            rebless_params => {
+                # Parameters to 'Breakable'
+                breakable_parts => [qw( tires wheels windscreen )],
+            }
+    });
 
-Copyright 2009 by Infinity Interactive, Inc.
+Obviously, this interface is better simplified as a method on C<Car>:
 
-L<http://www.iinteractive.com>
+    sub make_breakable {
+        my ( $self, %params ) = @_;
+        apply_all_roles($self, 'Breakable', { rebless_params => \%params });
+    }
 
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
+    my $car = Car->new();
+    $car->make_breakable( breakable_parts => [qw( tires wheels windscreen )] );
 
 =cut