From: Dave Rolsky Date: Wed, 11 Feb 2009 16:03:55 +0000 (+0000) Subject: Revised roles recipe 1 X-Git-Tag: 0.69~26 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=efaf28e977ce7fab4e67d604985a23cb1b9a121f;p=gitmo%2FMoose.git Revised roles recipe 1 --- diff --git a/lib/Moose/Cookbook/Roles/Recipe1.pod b/lib/Moose/Cookbook/Roles/Recipe1.pod index b8fdabe..5dc60cb 100644 --- a/lib/Moose/Cookbook/Roles/Recipe1.pod +++ b/lib/Moose/Cookbook/Roles/Recipe1.pod @@ -73,50 +73,41 @@ Moose::Cookbook::Roles::Recipe1 - The Moose::Role example =head1 DESCRIPTION -In this recipe we examine the role support provided in Moose. "Roles" may be -described in many ways, but there are two main ways in which they are used: as -interfaces, and as a means of code reuse. This recipe demonstrates the -construction and incorporation of roles that define comparison and display of -objects. +Roles have two primary purposes: as interfaces, and as a means of code +reuse. This recipe demonstrates the latter, with roles that define +comparison and display code for objects. -Let's start by examining B. You'll notice that instead of the familiar C you might be expecting, here we use C to make it clear that -this is a role. We encounter a new keyword, C: +Let's start with CB. First, note that we've replaced C +with C. We also have a new sugar function, C: requires 'equal_to'; -What this does is to indicate that any class which "consumes" (that is to say, -"includes using C", as we'll see a little later) the B role I -include an C method, whether this is provided by the class itself, one -of its superclasses, or another role consumed by the class (1). +This says that any class which consumes this role must provide an +C method. It can provide this method directly, or by +consuming some other role. -In addition to requiring an C method, B defines a C -method, which simply inverts the result of C. Defining additional -methods in this way, by using only a few base methods that target classes must -define, is a useful pattern to provide maximum functionality with minimum -effort. +The C role defines its C method in terms of the +required C method. This lets us minimize the methods that +consuming classes must provide. -After the minimal B, we next move on to B. The first thing you -will notice is another new keyword, C: +The next role, C, builds on the C role. We include +C in C using C, another new sugar function: with 'Eq'; -C is used to provide a list of roles which this class (or role) consumes. -Here, B only consumes one role (B). In effect, it is as if we -defined a C method within Comparable, and also promised to fulfill -the requirement of an C method. +The C function takes a list of roles to consume. In our example, +the C role provides the C method required by +C. However, it could opt not to, in which case a class that +consumed C would have to provide its own C. In +other words, a role can consume another role I providing any +required methods. -B itself states that it requires C. Again, it means that -any classes consuming this role must implement a C method. +The C role requires a method, C: requires 'compare'; -B defines an C method which satisfies the B role's -requirements. This, along with a number of other methods (C, -C, C, and C) is -simply defined in terms of C, once again demonstrating the pattern of -defining a number of utility methods in terms of only a single method that the -target class need implement. +The C role also provides a number of other methods, all of +which ultimately rely on C. sub equal_to { my ( $self, $other ) = @_; @@ -143,40 +134,39 @@ target class need implement. $self->less_than($other) || $self->equal_to($other); } -Next up is B. This is a very simple role, akin to B. It merely -requires a C method. Roles that only require methods are very much -like Java's interfaces. If we know that a class does the B role, it -not only tells us that we can call the C method on it, but also that -C has the precise semantics we want (consider classes B and -B, both with method C). +Finally, we the C role. This role exists solely to provide +an interface. It has no methods, just a list of required methods. In +this case, it just requires a C method. -Finally, we come to B, a class that allows us to reap the benefits -of our hard work. This is a regular Moose class, so we include the normal C. It consumes both B and B, as the following line -shows: +An interface role is useful because it defines both a method and a +I. We know that any class which does this role has a +C method, but we can also assume that this method has the +semantics we want. Presumably, in real code we would define those +semantics in the documentation for the C role. (1) + +Finally, we have the C class which consumes both the +C and C roles. with 'Comparable', 'Printable'; -It also defines a regular Moose attribute, C, with a type constraint of -C and a default of C<0>: +It also defines a regular Moose attribute, C: has 'amount' => ( is => 'rw', isa => 'Num', default => 0 ); -Now we come to the core of the class. First up, we define a C method: +Finally we see the implementation of the methods required by our +roles. We have a C method: sub compare { my ( $self, $other ) = @_; $self->amount <=> $other->amount; } -As you can see, it simply compares the C attribute of this object with -the C attribute of the other object passed to it. With the single -definition of this method, we gain the following methods for free: C, -C, C, C and +By consuming the C role and defining this method, we gain +the following methods for free: C, C, +C, C and C. -We end the class with a definition of the C method, which formats the -C attribute for display: +Then we have our C method: sub to_string { my $self = shift; @@ -185,8 +175,9 @@ C attribute for display: =head1 CONCLUSION -This recipe has shown that roles can be very powerful and immensely useful, and -save a great deal of repetition. +Roles can very powerful. They are a great way of encapsulating +reusable behavior, as well as communicating (semantic and interface) +information about the methods our classes provide. =head1 FOOTNOTES @@ -194,16 +185,20 @@ save a great deal of repetition. =item (1) -At present, method requirements from roles cannot be satisfied by attribute -accessors. This is a limitation of Moose, and will most likely be rectified in a -future release. +Consider two classes, C and C, both of which define a +C method. If we just require that an object implements a C +method, we still aren't saying anything about what that method +I. If we require an object that implements the +C role, we're saying something about semantics. =back -=head1 AUTHOR +=head1 AUTHORS Stevan Little Estevan@iinteractive.comE +Dave Rolsky Eautarch@urth.orgE + =head1 COPYRIGHT AND LICENSE Copyright 2006-2009 by Infinity Interactive, Inc.