From: Aankhen Date: Wed, 2 May 2007 06:47:22 +0000 (+0000) Subject: Moose::Cookbook::Recipe6: X-Git-Tag: 0_21~3 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=cb26ee7e733b14eb6a6fa0a7e708ed8883cce103;p=gitmo%2FMoose.git Moose::Cookbook::Recipe6: * first shot at adding a description for the recipe. --- diff --git a/lib/Moose/Cookbook/Recipe6.pod b/lib/Moose/Cookbook/Recipe6.pod index 39e812f..2334e53 100644 --- a/lib/Moose/Cookbook/Recipe6.pod +++ b/lib/Moose/Cookbook/Recipe6.pod @@ -70,10 +70,131 @@ Moose::Cookbook::Recipe6 - The Moose::Role example my $self = shift; sprintf '$%0.2f USD' => $self->amount } - + =head1 DESCRIPTION -Coming Soon. +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. + +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: + + 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). + +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. + +After the minimal B, we next move on to B. The first thing you +will notice is another new keyword, C: + + 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. + +B itself states that it requires C. Again, it means that +any classes consuming this role must implement a C method. + + 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. + + sub equal_to { + my ($self, $other) = @_; + $self->compare($other) == 0; + } + + sub greater_than { + my ($self, $other) = @_; + $self->compare($other) == 1; + } + + sub less_than { + my ($self, $other) = @_; + $self->compare($other) == -1; + } + + sub greater_than_or_equal_to { + my ($self, $other) = @_; + $self->greater_than($other) || $self->equal_to($other); + } + + sub less_than_or_equal_to { + my ($self, $other) = @_; + $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. + +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: + + with 'Comparable', 'Printable'; + +It also defines a regular Moose attribute, C, with a type constraint of +C and a default of C<0>: + + has 'amount' => (is => 'rw', isa => 'Num', default => 0); + +Now we come to the core of the class. First up, we define 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 +C. + +We end the class with a definition of the C method, which formats the +C attribute for display: + + sub to_string { + my $self = shift; + sprintf '$%0.2f USD' => $self->amount + } + +=head1 CONCLUSION + +This recipe has shown that roles can be very powerful and immensely useful, and +save a great deal of repetition. + +=head1 FOOTNOTES + +=over 4 + +=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. + +=back =head1 AUTHOR