=pod =head1 NAME Moose::Cookbook::Roles::Recipe1 - The Moose::Role example =head1 SYNOPSIS package Eq; use Moose::Role; requires 'equal_to'; sub not_equal_to { my ( $self, $other ) = @_; not $self->equal_to($other); } package Comparable; use Moose::Role; with 'Eq'; requires 'compare'; 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); } package Printable; use Moose::Role; requires 'to_string'; package US::Currency; use Moose; with 'Comparable', 'Printable'; has 'amount' => ( is => 'rw', isa => 'Num', default => 0 ); sub compare { my ( $self, $other ) = @_; $self->amount <=> $other->amount; } sub to_string { my $self = shift; sprintf '$%0.2f USD' => $self->amount; } =head1 DESCRIPTION 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 with CB. First, note that we've replaced C with C. We also have a new sugar function, C: requires 'equal_to'; 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. 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. The next role, C, builds on the C role. We include C in C using C, another new sugar function: with 'Eq'; 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. The C role requires a method, C: requires 'compare'; The C role also provides a number of other methods, all of which ultimately rely on C. 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); } 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. 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: has 'amount' => ( is => 'rw', isa => 'Num', default => 0 ); 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; } By consuming the C role and defining this method, we gain the following methods for free: C, C, C, C and C. Then we have our C method: sub to_string { my $self = shift; sprintf '$%0.2f USD' => $self->amount; } =head1 CONCLUSION 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 =over 4 =item (1) 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 AUTHORS Stevan Little Estevan@iinteractive.comE Dave Rolsky Eautarch@urth.orgE =head1 COPYRIGHT AND LICENSE Copyright 2006-2009 by Infinity Interactive, Inc. L This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut