Search code examples
perlmoose

How can I change an overloaded operator on a Moose class at runtime?


I have a Moose class with an overloaded stringification operator which I would actually like to change at runtime, because I need text output in different formats.

In other words, I would like to be able to do something like this:

$obj = Class->new("a'");
$obj->formatter("A::Formatter");
print "$obj";

# prints "a'"

$obj->formatter("Another::Formatter");
print "$obj";

# prints a1

I would also like the formatters to be modular, so that I can encapsulate and plug in different ones without creating a giant spaghetti mess.

How should I best do this? are roles a good solution for this kind of problem? I have checked MooseX::Object::Pluggable, MooseX::Traits::Pluggable and MooseX::Traits to start but need advice as this is uncharted territory for me.


Solution

  • You don't need to change the overloading at runtime, just how it's implemented. Remember, overloading can be done with a method name as opposed to a subref:

    package Foo;
    
    use Moose;
    
    use overload q{""} => '_stringify';
    
    has id => (
        is       => 'ro',
        isa      => 'Str',
        required => 1,
    );
    
    has formatter_class => (
        is       => 'rw',
        isa      => 'ClassName',
        required => 1,
    );
    
    sub _stringify {
        my $self = shift;
        return $self->formatter_class()->new()->format($self);
    }