Taming the Moose: Picking the best way to subclass Perl methods
Tags: moose, oop, perl
Published: 2021-07-13 14:33:37

---
title: Taming the Moose: Picking the best way to subclass Perl methods
published: true
date: 2021-07-13 14:00:00 UTC
tags: Moose,OOP,Perl
canonical_url: https://phoenixtrap.com/2021/07/13/taming-the-moose-picking-the-best-way-to-subclass-perl-methods/
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9iqwe48oo9fzigmicgac.jpeg
series: Taming the Moose
---

The `override` keyword in Perl’s [Moose](https://metacpan.org/pod/Moose) object system is a nice bit of code-as-documentation since it explicitly states that a given method overrides from its superclass. It also has a `super` keyword that can be used inside an `override`, calling “the next most appropriate superclass method with the same arguments as the original method.”

The Moose documentation then goes on to say, “The same thing _can_ be accomplished with a normal method call and the [`SUPER::`](https://perldoc.pl/perlobj#Inheritance) pseudo-package; it is really your choice.” So when should you use one and not the other? I decided to find out.

First I defined a simple Moose superclass with a single method:

```perl
package Local::MyClass;

use Moose;

sub my_method {
    return blessed $_[0];
}

__PACKAGE__ ->meta->make_immutable();

1;
```

And then a pair of subclasses, one using Moose’s `override` keyword and one with a plain `sub`:

```perl
package Local::MyClass::MyChildOverride;

use Moose;
extends 'Local::MyClass';

override my_method => sub {
    my $self = shift;
    return 'child ' . super;
};

__PACKAGE__ ->meta->make_immutable();

1;
```

```perl
package Local::MyClass::MyChildPlain;

use Moose;
extends 'Local::MyClass';

sub my_method {
    my $self = shift;
    return 'child ' . $self->SUPER::my_method();
}

__PACKAGE__ ->meta->make_immutable();

1;
```

So far so good, and both can be called successfully:

```
$ perl -Ilib -MLocal::MyClass::MyChildPlain \
  -MLocal::MyClass::MyChildOverride \
  -E '$PREFIX = "Local::MyClass::MyChild";
  for ( qw(Plain Override) ) {
    $object = "$PREFIX$_"->new();
    say $object->my_method()
  }'
child Local::MyClass::MyChildPlain
child Local::MyClass::MyChildOverride
```

Let’s toss in a new wrinkle, though. What if we forgot to define the method in the superclass?

```perl
package Local::MyClassNoMethod;

use Moose;

__PACKAGE__ ->meta->make_immutable();

1;
```

Both ways of calling the superclass’s method will bug out, of course, but unlike a plain override Moose will actually prevent you from `use`ing the offending subclass during the `BEGIN` phase:

```
$ perl -Ilib -MLocal::MyClassNoMethod::MyChildOverride \
  -E ''
You cannot override 'my_method' because it has no super method at /Users/mgardner/.plenv/versions/5.34.0/lib/perl5/site_perl/5.34.0/darwin-2level/Moose/Exporter.pm line 419
	Moose::override('my_method', 'CODE(0x7fe5cb811a88)') called at lib/Local/MyClassNoMethod/MyChildOverride.pm line 9
	require Local/MyClassNoMethod/MyChildOverride.pm at -e line 0
	main::BEGIN at lib/Local/MyClassNoMethod/MyChildOverride.pm line 0
	eval {...} at lib/Local/MyClassNoMethod/MyChildOverride.pm line 0
Compilation failed in require.
BEGIN failed--compilation aborted.
```

With plain method overriding, you only get an error if you try to call the superclass’s method. If your overridden method doesn’t do that, it’s perfectly safe to define and call. It’s only if you use that `SUPER::` pseudo-package that things blow up at runtime:

```
$ perl -Ilib -MLocal::MyClassNoMethod::MyChildPlain \
  -E '$obj = Local::MyClassNoMethod::MyChildPlain->new();
  $obj->my_method()'
Can't locate object method "my_method" via package "Local::MyClassNoMethod::MyChildPlain" at lib/Local/MyClassNoMethod/MyChildPlain.pm line 8.
```

Note that **none of this is caught at compile time**. `perl -c` will happily compile all these classes and subclasses without a peep:

```
$ find . -name '*.pm' -exec perl -c {} \;
./lib/Local/MyClass/MyChildPlain.pm syntax OK
./lib/Local/MyClass/MyChildOverride.pm syntax OK
./lib/Local/MyClassNoMethod/MyChildPlain.pm syntax OK
./lib/Local/MyClassNoMethod/MyChildOverride.pm syntax OK
./lib/Local/MyClass.pm syntax OK
./lib/Local/MyClassNoMethod.pm syntax OK
```

So what can we conclude? Moose’s `override` is a good way of describing your intent with a subclass, and it will catch you out if you try to use it without a corresponding method in a superclass. **It is a non-standard keyword though** , so syntax-highlighting editors and code analysis tools won’t recognize it unless taught. Further, if your subclass method doesn’t call the same method in a superclass you could eventually get away with removing the latter if you use a plain `sub`.

I’ve created a [small GitHub project](https://github.com/mjgardner/moose_override) with the sample code from this article, including test scripts.

What do you think? Is `override` suitable for your Moose projects, or are you satisfied with plain `sub`? Let me know in the comments.