oop intermediate

How to convert a Perl Moo class to Moose?

Question

How to convert a Perl Moo class to Moose?

Converting a Perl Moo class to Moose is a common task when you want to leverage Moose's richer feature set, such as method modifiers, type constraints, or metaclasses, while having initially developed your code using the lightweight Moo framework. Since Moo was designed to be mostly compatible with Moose but without its heavier runtime, the migration is often straightforward.

Key Differences Between Moo and Moose

  • Base class: Moo uses use Moo; vs Moose uses use Moose;.
  • Attributes: Mostly similar syntax, but Moose supports richer attribute options (e.g., traits, isa type constraints, coercions).
  • Method modifiers: Both support before, after, and around, but Moose’s are more feature-rich.
  • Immutable: Moose recommends calling __PACKAGE__->meta->make_immutable for performance. Moo has no equivalent.
  • Dependencies: Moose has many more dependencies and a heavier runtime.

Basic Conversion Steps

  1. Change use Moo; to use Moose;.
  2. Adjust attributes if needed to add Moose-only features (e.g., isa type constraints).
  3. Add __PACKAGE__->meta->make_immutable; at the end of the package to improve performance.
  4. Review your method modifiers and extensions; Moose allows more flexibility (e.g., method handles, method aliases).
  5. Test thoroughly, because some Moo features default differently (e.g., required attribute behavior).

Sample Conversion

Here’s a runnable example demonstrating a simple Moo class converted to Moose.

use strict;
use warnings;

# Original Moo class
package PersonMoo;
use Moo;

has 'name' => (
    is       => 'ro',
    required => 1,
);

has 'age' => (
    is      => 'rw',
    default => sub { 20 },
);

sub greet {
    my $self = shift;
    return "Hello, my name is " . $self->name . " and I am " . $self->age . " years old.";
}

1;

# Converted Moose class
package PersonMoose;
use Moose;

has 'name' => (
    is       => 'ro',
    isa      => 'Str',
    required => 1,
);

has 'age' => (
    is      => 'rw',
    isa     => 'Int',
    default => sub { 20 },
);

sub greet {
    my $self = shift;
    return "Hello, my name is " . $self->name . " and I am " . $self->age . " years old.";
}

__PACKAGE__->meta->make_immutable;

1;

# Script to test both
package main;

my $m_person = PersonMoo->new(name => 'Alice');
print $m_person->greet () . "\n";

my $ms_person = PersonMoose->new(name => 'Bob', age => 35);
print $ms_person->greet () . "\n";

Explanation

  • Moo and Moose syntax for has is very similar; the main difference is that with Moose you can specify type constraints with isa (e.g., Str, Int).
  • required => 1 works the same in both, signaling the attribute must be passed to the constructor.
  • The default coderef syntax is identical.
  • Moose classes should call __PACKAGE__->meta->make_immutable for improved speed and reduced memory usage.
  • The rest of the code (methods like greet) remains unchanged.

Common Gotchas

  • Required attributes: Moo’s required is less strict if lazily built attributes are involved; Moose enforces this more properly.
  • Build methods: Moo does not autogenerate BUILD or DEMOLISH methods; Moose expects and calls them during construction and destruction.
  • Type constraints: You’ll want to add isa declarations explicitly in Moose — this is a great time to add type safety.
  • Immutable: Forgetting make_immutable in Moose will cause slower object creation.
  • Dependencies: Moose is heavier; consider whether you need the extra features before converting.

In summary, converting a Moo class to Moose involves changing the import, adding type constraints, and finishing with make_immutable. Because Moo was designed to be mostly compatible with Moose, your existing code will often require minimal changes.

Verified Code

Executed in a sandbox to capture real output. • v5.34.1 • 245ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Hello, my name is Alice and I am 20 years old.
Hello, my name is Bob and I am 35 years old.
STDERR
(empty)

Was this helpful?

Related Questions