Multiple ways to inheritance in Perl
Tags: perl, oop, cpan, inheritance
Published: 2021-11-16 16:50:49

---
title: Multiple ways to inheritance in Perl
published: true
date: 2021-11-16 15:00:00 UTC
tags: Perl,OOP,CPAN,inheritance
canonical_url: https://phoenixtrap.com/2021/11/16/multiple-ways-to-inheritance-in-perl/
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9jj47r2ax9ein5le9vt.jpeg
---

Inspired by my parents coming to visit at the end of the week, I thought I’d write about how Perl classes can have “parents” as well, from which they inherit methods. Although it might seem on the surface as though [there’s more than one way to do it](https://en.wikipedia.org/wiki/There's_more_than_one_way_to_do_it), these techniques all share the same underlying mechanism.

## Where it all [`BEGIN`](https://perldoc.perl.org/perlmod#BEGIN%2C-UNITCHECK%2C-CHECK%2C-INIT-and-END)s: [`@ISA`](https://perldoc.perl.org/variables/@ISA)

Perl classes are just repurposed [`package`](https://perldoc.perl.org/functions/package)s, i.e., a namespace for variables and subroutines. The two key differences are:

- Subroutines may expect either an [object reference](https://perldoc.perl.org/perlref#Constructors) or the name of a class as their first argument.
- When you call a method that isn’t defined in a class, Perl will search through the [special `@ISA` array](https://perldoc.perl.org/variables/@ISA) in the package for the name of a class that has that method. (You can change the search order with [the `mro` (method resolution order) pragma](https://perldoc.perl.org/mro).)

If you wanted to do everything by hand at the lowest level, you could make a subclass at compile time like this:

```perl
package Local::MyChildClass;
BEGIN { # don't do this:
    require Local::MyParentClass;
    push @ISA, 'Local::MyParentClass';
}
```

Don’t do that though, because we have…

## [`base`](https://perldoc.perl.org/base) and [`parent`](https://perldoc.perl.org/parent)

In 1997 [Perl 5.004\_04 introduced](https://perldoc.perl.org/base#HISTORY) the `base` pragma (back when Perl used that kind of versioning scheme; in these days of [semantic versioning](https://semver.org/) we’d call it version 5.4.4). It does the above [`BEGIN` block](https://perldoc.perl.org/perlmod#BEGIN%2C-UNITCHECK%2C-CHECK%2C-INIT-and-END) in a single line:

```perl
use base 'Local::MyParentClass'; # don't do this unless you're also using fields
```

You might see `use base` in older code especially if it’s also using the [`fields`](https://perldoc.perl.org/fields) pragma. However, Perl developers [discourage](https://perldoc.perl.org/perlpolicy#discouraged) both as the former [silences certain module loading errors](https://stackoverflow.com/a/37530787/638877) while the latter is at odds with the object-oriented programming principle of [encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)).

So `use parent` instead, which Perl has included [since version 5.10.1](https://perldoc.perl.org/perl5101delta#parent) in 2009:

```perl
use parent 'Local::MyParentClass';
```

A couple of years ago my [Newfold Digital](https://newfold.com/) colleague [David Oswald](http://blogs.perl.org/users/david_oswald/) created a fork of parent called [parent::versioned](https://metacpan.org/pod/parent::versioned) that supports specifying the lowest version for superclasses. You call it like this:

```perl
use parent::versioned ['Local::MyParentClass' => 1.23];
```

## Within an OO system

There are dozens of [object-oriented programming systems](https://perldoc.perl.org/perlootut#PERL-OO-SYSTEMS) on [CPAN](https://www.cpan.org/) that provide [syntactic sugar](https://en.wikipedia.org/wiki/Syntactic_sugar) and extra features to Perl’s minimal but flexible [basics](https://perldoc.perl.org/perlobj). Two of the more popular ones, [Moose](https://metacpan.org/pod/Moose) and [Moo](https://metacpan.org/pod/Moo), offer an `extends` keyword that you should use instead of `use parent` so that your subclasses may take advantage of their features:

```perl
package Local::MyChildClass;
use Moo;
extends 'Local::MyParentClass';
```

Moose can also specify a required superclass version:

```perl
package Local::MyChildClass;
use Moose;
extends 'Local::MyParentClass' => {-version => 1.23};
```

Also, use the [MooseX::NonMoose](https://metacpan.org/pod/MooseX::NonMoose) module when extending non-Moose classes, again so you get Moose features even though your methods are coming from somewhere else:

```perl
package Local::MyMooseClass;
use Moose;
use MooseX::NonMoose;
extends 'Local::MyPlainParentClass';
```

The experimental [Object::Pad](https://metacpan.org/pod/Object::Pad) module specifies a single superclass while defining the class name with an optional version. Per the author’s [suggested file layout](https://metacpan.org/pod/Object::Pad#File-Layout), including a required minimum version, it would look like:

```perl
use Object::Pad 0.41;
package Local::MyChildClass;
class Local::MyChildClass isa Local::MyParentClass 1.23;
```

Object::Pad and [Corinna](https://github.com/Ovid/Cor/wiki), its inspiration, are works in progress so this syntax isn’t set in stone. The latter’s designer Curtis “Ovid” Poe [blogged earlier this week](https://ovid.github.io/articles/language-design-consistency.html) about considering a more self-consistent syntax.

## [Multiple inheritance](https://perldoc.perl.org/perlobj#Multiple-Inheritance) vs. [roles](https://perldoc.perl.org/perlootut#Roles)

To quote the [Perl documentation](https://perldoc.perl.org/perlobj#Multiple-Inheritance), “multiple inheritance often indicates a design problem, but Perl always gives you enough rope to hang yourself with if you ask for it.” All the techniques described above except for Object::Pad support multiple inheritance by specifying a list of superclasses. For example:

```perl
package Local::MyChildClass;
use parent qw(Local::MyParentClass1 Local::MyParentClass2);
```

If you’re using roles instead of or on top of superclasses (I’ve seen both situations) and your OO system doesn’t support them on its own, you can use [the Role::Tiny module](https://metacpan.org/pod/Role::Tiny), first by describing your role in one package and then consuming it in another:

```perl
package Local::DoesSomething;
use Role::Tiny;

...

1;
```

```perl
package Local::MyConsumer;
use Role::Tiny::With;
with 'Local::DoesSomething';

...

1;
```

[Moo::Role](https://metacpan.org/pod/Moo::Role) uses Role::Tiny under the hood and Moo can compose roles from either. The syntax for both Moo and Moose is similar:

```perl
package Local::DoesSomething;
use Moo::Role; # or "use Moose::Role;"

...

1;
```

```perl
package Local::MyConsumer;
use Moo; # or "use Moose;"
with 'Local::DoesSomething';

...

1;
```

Object::Pad specifies roles with the [`role` keyword](https://metacpan.org/pod/Object::Pad#role), and both classes and roles use `does` to consume them:

```perl
use Object::Pad 0.56;
package Local::DoesSomething;
role Local::DoesSomething does Local::DoesSomethingElse;

...

1;
```

```perl
use Object::Pad 0.56;
package Local::MyConsumer;
class Local::MyConsumer does Local::DoesSomething;

...

1;
```

The [previous caveat](#CorinnaConsistency) about possible changes to this syntax applies.

## Like parent, (sort of) like child

Of course, the whole point of inheritance or role consumption is so your child or consumer class can reuse functions and methods. Each of the techniques above has its ways of overriding that code, from the Perl built-in [`SUPER` pseudo-class](https://perldoc.perl.org/perlobj#How-SUPER-is-Resolved) to Moose’s [`override`](https://metacpan.org/pod/Moose#override-(%24name,-&sub)) and [`super`](https://metacpan.org/pod/Moose#super) keywords, to [Moose’s](https://metacpan.org/pod/Moose::Manual::MethodModifiers) and [Moo’s](https://metacpan.org/pod/Class::Method::Modifiers) method modifiers. (You can use the latter outside of Moo since it’s provided by [Class::Method::Modifiers](https://metacpan.org/pod/Class::Method::Modifiers).)

I’ve written about choosing between [overriding](https://phoenixtrap.com/2021/07/13/taming-the-moose-picking-the-best-way-to-subclass-perl-methods/) and [modifying methods](https://phoenixtrap.com/2021/08/31/taming-the-moose-method-modifiers-instead-of-overrides-in-object-oriented-perl/) before, and when it comes to Moose and Moo code I’m now on the side of using the [`around` method modifier](https://metacpan.org/dist/Moose/view/lib/Moose/Manual/MethodModifiers.pod#Around-modifiers) if a method needs to call an inherited or consumed method of the same name. Object::Pad doesn’t have method modifiers (yet), so `class`es that use it will have to satisfy themselves with `SUPER` in their [`method`](https://metacpan.org/pod/Object::Pad#method)s with an `:override` attribute that will throw an error if a parent doesn’t also provide the same method.

## The Parent Wrap

In the end, your [choice of Perl OO system](https://perldoc.perl.org/perlootut#PERL-OO-SYSTEMS) will determine how (or whether) you handle inheritance and may even be a deciding factor. Which would you choose? And more importantly, have I made my parents proud with this post?