How to implement method delegation in Perl Moo?
Question
How to implement method delegation in Perl Moo?
In Perl object-oriented programming, Moo is a lightweight object system providing many modern OO features. One common pattern is method delegation, where an object forwards method calls to an attribute’s underlying object, reducing boilerplate code.
With Moo, you can easily implement delegation using the handles attribute option when defining an attribute. This instructs Moo to automatically create delegation methods in your class that forward to the attribute’s methods.
How to Use handles in Moo for Delegation
You define an attribute that holds an object and specify which methods it should delegate by passing method names or method name mappings in the handles attribute option.
handles => ['foo', 'bar']delegates calls forfoo()andbar()to the contained object.handles => { new_name => 'original_name' }lets you rename the delegated method.- Delegation helps encapsulate components cleanly, avoids repetitive wrapper methods, and supports composition over inheritance.
Perl Code Example
use strict;
use warnings;
use feature 'say';
use Moo;
# This class represents a Logger object
package Logger {
sub new { bless {}, shift }
sub log_info { my ($self, $msg) = @_; say "[INFO]: $msg" }
sub log_warn { my ($self, $msg) = @_; say "[WARN]: $msg" }
}
# This class contains a Logger and delegates logging methods to it
package MyApp {
use Moo;
has logger => (
is => 'ro',
default => sub { Logger->new },
handles => {
info => 'log_info', # delegate info() -> log_info()
warn => 'log_warn', # delegate warn() -> log_warn()
},
);
sub run {
my ($self) = @_;
$self->info("Starting application");
$self->warn("This is just a warning");
}
}
package main;
my $app = MyApp->new;
$app->run;
Explanation:
Loggeris a simple class withlog_infoandlog_warnmethods.MyApphas aloggerattribute holding aLoggerobject. The attribute useshandlesto delegateinfoandwarnmethods to those inLogger.- When calling
$app->info(...), it actually calls$app->logger->log_info(...)transparently. - This avoids writing explicit forwarding methods, following the Perl motto TMTOWTDI (There’s More Than One Way To Do It) elegantly.
Key Points about handles Delegation in Moo
- Sigil Note: The attribute is accessed as
$self->loggerinternally. The delegated methods belong to the attribute’s object. - Delegation can be to a single method (as string), a list of methods (array ref), or a hash ref for renaming.
- Attempting to delegate to a method not present in the delegated-to object will raise an error at runtime.
Moosupports lazy attribute building, so delegation works smoothly with lazy attributes too.- This feature has been stable since early Moo releases (
perl 5.10+compatible).
Common Pitfalls and Gotchas
- Delegation only works if the attribute contains a valid object implementing the delegated methods.
- Make sure to declare the delegated methods correctly—typos lead to runtime errors.
- You can delegate only instance methods, not class methods.
- You cannot delegate to functions or packages that are not objects.
- If you override delegated method names manually in your class, delegation methods might be overridden.
In summary, method delegation in Moo is straightforward and a great way to compose behavior by forwarding methods from contained attributes. Using the handles option with your attributes lets you keep your classes concise, readable, and maintain a clean separation of responsibilities.
Verified Code
Executed in a sandbox to capture real output. • v5.34.1 • 35ms
[INFO]: Starting application
[WARN]: This is just a warning
(empty)Was this helpful?
Related Questions
- How to use Moose::Util::TypeConstraints for custom types?
- How to use Type::Tiny with Moo for strict typing in Perl?
- How to use required attributes in Perl Moo and Moose?
- How to convert a Perl Moo class to Moose?
- How to use Moo lazy_build for attribute defaults in Perl?
- How to implement multiple inheritance with Moose in Perl?