Document how to pass new attribute values at instance-role application time
[gitmo/Moose.git] / lib / Moose / Manual / Roles.pod
index 45265e4..009a2ea 100644 (file)
@@ -1,19 +1,21 @@
-=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>. 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.
+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. A subclass of the consuming class
@@ -28,7 +30,7 @@ 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. 
+purposes of satisfying the requirements of a role.
 
 =head1 A SIMPLE ROLE
 
@@ -75,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
 
@@ -100,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
@@ -171,10 +175,10 @@ 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.
+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;
 
@@ -186,9 +190,9 @@ I<before> the C<with> function that composes the role.
 
   use Moose;
 
-  has 'stress' => ( 
+  has 'stress' => (
       is  => 'rw',
-         isa => 'Int',
+      isa => 'Int',
   );
 
   with 'Breakable';
@@ -212,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>.
@@ -242,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
@@ -280,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
@@ -292,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