more work on the manual, notably mostly finishing the Roles document
Dave Rolsky [Fri, 9 Jan 2009 03:43:49 +0000 (03:43 +0000)]
lib/Moose/Manual.pod
lib/Moose/Manual/Roles.pm

index 5e7d4c0..e4a31b6 100644 (file)
@@ -166,11 +166,10 @@ section is for you.
 
 =item Another object system!?!?
 
-Yes, I know there has been an explosion recently of new ways to
-build objects in Perl 5, most of them based on inside-out objects
-and other such things. Moose is different because it is not a new
-object system for Perl 5, but instead an extension of the existing
-object system.
+Yes, I know there are many, many ways to build objects in Perl 5, many
+of them based on inside-out objects and other such things. Moose is
+different because it is not a new object system for Perl 5, but
+instead an extension of the existing object system.
 
 Moose is built on top of L<Class::MOP>, which is a metaclass system
 for Perl 5. This means that Moose not only makes building normal
@@ -187,10 +186,10 @@ prototype; it is for B<real>.
 
 Yes.
 
-Moose has been used successfully in production environments by several
+Moose has been used successfully in production environments by many
 people and companies. There are Moose applications which have been in
-production with little or no issue now for well over two years. We
-consider it highly stable and we are commited to keeping it stable.
+production with little or no issue now for well years. We consider it
+highly stable and we are commited to keeping it stable.
 
 Of course, in the end, you need to make this call yourself. If you
 have any questions or concerns, please feel free to email Stevan, the
index 8be2659..cfdace1 100644 (file)
@@ -68,11 +68,11 @@ 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() );
+  my $car = Car->new( engine => Engine->new );
 
-  print $car->is_broken() ? 'Still working' : 'Busted';
-  $car->break();
-  print $car->is_broken() ? 'Still working' : 'Busted';
+  print $car->is_broken ? 'Still working' : 'Busted';
+  $car->break;
+  print $car->is_broken ? 'Still working' : 'Busted';
 
   $car->does('Breakable'); # true
 
@@ -117,7 +117,7 @@ methods:
       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.
@@ -133,7 +133,7 @@ is always set to true when C<break> is called.
 
   package Car
 
-  use Moose;
+      use Moose;
 
   with 'Breakable';
 
@@ -145,8 +145,8 @@ is always set to true when C<break> is called.
   sub break {
       my $self = shift;
 
-      if ( $self->is_moving() ) {
-          $self->stop();
+      if ( $self->is_moving ) {
+          $self->stop;
       }
   }
 
@@ -157,9 +157,9 @@ 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 two roles, each
-of which modify the same method, those modifiers will be applied in
-the same order as the roles are used:
+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;
 
@@ -197,3 +197,40 @@ provide our own C<break> method:
 
   with 'Breakable', 'Breakdancer';
 
+  sub break { ... }
+
+=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' },
+      exclude => 'break',
+      },
+      'Breakdancer' => {
+      alias   => { break => 'break_dance' },
+      exclude => 'break',
+      };
+
+The exclude 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.
+