---
name: "Moose::Cookbook::Roles::Comparable_CodeReuse"
section: "3pm"
platform: "linux"
package: "perl-moose"
version: "2.4001-2"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/Moose::Cookbook::Roles::Comparable_CodeReuse"
---

# Moose::Cookbook::Roles::Comparable\_CodeReuse(3pm)

Using roles for code reuse

## NAME

Moose::Cookbook::Roles::Comparable\_CodeReuse - Using roles for code reuse

## VERSION

version 2.4001

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

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 `"Eq"`. First, note that we've replaced `"use Moose"` with `"use Moose::Role"`. We also have a new sugar function, `"requires"`:

```
  requires 'equal_to';
```

This says that any class which consumes this role must provide an `"equal_to"` method. It can provide this method directly, or by consuming some other role.

The `"Eq"` role defines its `"not_equal_to"` method in terms of the required `"equal_to"` method. This lets us minimize the methods that consuming classes must provide.

The next role, `"Comparable"`, builds on the `"Eq"` role. We include `"Eq"` in `"Comparable"` using `"with"`, another new sugar function:

```
  with 'Eq';
```

The `"with"` function takes a list of roles to consume. In our example, the `"Comparable"` role provides the `"equal_to"` method required by `"Eq"`. However, it could opt not to, in which case a class that consumed `"Comparable"` would have to provide its own `"equal_to"`. In other words, a role can consume another role *without* providing any required methods.

The `"Comparable"` role requires a method,  `"compare"`:

```
  requires 'compare';
```

The `"Comparable"` role also provides a number of other methods, all of which ultimately rely on `"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);
  }
```

Finally, we define the `"Printable"` 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 `"to_string"` method.

An interface role is useful because it defines both a method and a *name*. We know that any class which does this role has a `"to_string"` 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 `"Printable"` role. (1)

Finally, we have the `"US::Currency"` class which consumes both the `"Comparable"` and `"Printable"` roles.

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

It also defines a regular Moose attribute, `"amount"`:

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

Finally we see the implementation of the methods required by our roles. We have a `"compare"` method:

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

By consuming the `"Comparable"` role and defining 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"`.

Then we have our `"to_string"` method:

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

## CONCLUSION

Roles can be 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.

## FOOTNOTES

- (1)

  Consider two classes, `"Runner"` and `"Process"`, both of which define a `"run"` method. If we just require that an object implements a `"run"` method, we still aren't saying anything about what that method *actually does*. If we require an object that implements the `"Executable"` role, we're saying something about semantics.

## AUTHORS

- •

  Stevan Little \<stevan@cpan.org\>

- •

  Dave Rolsky \<autarch@urth.org\>

- •

  Jesse Luehrs \<doy@cpan.org\>

- •

  Shawn M Moore \<sartak@cpan.org\>

- •

  יובל קוג'מן (Yuval Kogman) \<nothingmuch@woobling.org\>

- •

  Karen Etheridge \<ether@cpan.org\>

- •

  Florian Ragwitz \<rafl@debian.org\>

- •

  Hans Dieter Pearcey \<hdp@cpan.org\>

- •

  Chris Prather \<chris@prather.org\>

- •

  Matt S Trout \<mstrout@cpan.org\>

## COPYRIGHT AND LICENSE

This software is copyright (c) 2006 by Infinity Interactive, Inc.

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