---
name: "Moose::Cookbook::Recipe10"
section: "3pm"
platform: "linux"
package: "libmoose-perl"
version: "0.54-1"
release: "Debian 5.0 (Lenny)"
platforms: ["linux"]
url: "https://new.carta.tech/Moose::Cookbook::Recipe10"
---

# Moose::Cookbook::Recipe10(3pm)

The Moose::Role example

## NAME

Moose::Cookbook::Recipe10 - The Moose::Role example

## 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
  }
```

## 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.

Let's start by examining **Eq**. You'll notice that instead of the familiar `"use` `Moose"` you might be expecting, here we use `"Moose::Role"` to make it clear that this is a role. We encounter a new keyword, `"requires"`:

```
  requires 'equal_to';
```

What this does is to indicate that any class which "consumes" (that is to say, "includes using `"with"`", as we'll see a little later) the **Eq** role *must* include an `"equal_to"` 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 `"equal_to"` method, **Eq** defines a `"not_equal_to"` method, which simply inverts the result of `"equal_to"`. 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 **Eq**, we next move on to **Comparable**. The first thing you will notice is another new keyword, `"with"`:

```
  with 'Eq';
```

`"with"` is used to provide a list of roles which this class (or role) consumes. Here, **Comparable** only consumes one role (**Eq**). In effect, it is as if we defined a `"not_equal_to"` method within Comparable, and also promised to fulfill the requirement of an `"equal_to"` method.

**Comparable** itself states that it requires `"compare"`. Again, it means that any classes consuming this role must implement a `"compare"` method.

```
  requires 'compare';
```

**Comparable** defines an `"equal_to"` method which satisfies the **Eq** role's requirements. This, along with a number of other methods (`"greater_than"`, `"less_than"`, `"greater_than_or_equal_to"`, and `"less_than_or_equal_to"`) is simply defined in terms of `"compare"`, 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 **Printable**. This is a very simple role, akin to **Eq**. It merely requires a `"to_string"` method.

Finally, we come to **US::Currency**, a class that allows us to reap the benefits of our hard work. This is a regular Moose class, so we include the normal `"use` `Moose"`. It consumes both **Comparable** and **Printable**, as the following line shows:

```
  with 'Comparable', 'Printable';
```

It also defines a regular Moose attribute, `"amount"`, with a type constraint of `"Num"` and a default of `0`:

```
  has 'amount' => (is => 'rw', isa => 'Num', default => 0);
```

Now we come to the core of the class. First up, we define a `"compare"` method:

```
  sub compare {
      my ($self, $other) = @_;
      $self->amount <=> $other->amount;
  }
```

As you can see, it simply compares the `"amount"` attribute of this object with the `"amount"` attribute of the other object passed to it. With the single definition of this method, we gain the following methods for free: `"equal_to"`, `"greater_than"`, `"less_than"`, `"greater_than_or_equal_to"` and `"less_than_or_equal_to"`.

We end the class with a definition of the `"to_string"` method, which formats the `"amount"` attribute for display:

```
  sub to_string {
      my $self = shift;
      sprintf '$%0.2f USD' => $self->amount
  }
```

## CONCLUSION

This recipe has shown that roles can be very powerful and immensely useful, and save a great deal of repetition.

## FOOTNOTES

- (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.

## AUTHOR

Stevan Little \<stevan@iinteractive.com\>

## COPYRIGHT AND LICENSE

Copyright 2006-2008 by Infinity Interactive, Inc.

\<http://www.iinteractive.com\>

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
