Horizontal Reuse: An Alternative to Inheritance

Comparing Perl's Moose with Java, Ruby, and PHP

photo: Jorge Royan

In class-based object-oriented programming, when there are classes that appear to share some functionality, this is often a time when people will refactor them into two subclasses of a common base class, avoiding repetition.

For example, in my farm model the Horse class and the Tractor class each implement a pull_plough method. (American readers might prefer pull_plow.) So this method is a candidate to split out into a Hitchable class for Horse and Tractor to each inherit from.

This would have nice benefits for polymorphism. I’ll be able to pass an object to my Farmer which will only need to check that the object inherits from Hitchable rather than having a hard-coded list of classes like Horse and Tractor that it knows are acceptable.

However, Horse already inherits from Animal, and Tractor already inherits from Vehicle. Even in programming languages that support multiple inheritance (and not all do; Java and PHP are two prominent languages that do not), multiple inheritance is often seen as problematic.

So ruling out multiple inheritance, what other possibilities do we have? Well, perhaps Animal and Vehicle both inherit from a common FarmAsset class – we could add pull_ploughto that. But a moment’s reflection rules that out; chickens can’t pull ploughs.

What we want is some way to package up the pull_plough behaviour in one place where the bundle of behaviour can be documented, and give it a name so code can check whether an object implements this bundle of behaviour.

Java

Java offers us interfaces for this purpose.

The Hitchable interface provides a name for this bundle of behaviour which we can check using Java’s instanceof operator. However, interfaces are forbidden from including any method implementations, so we still need to copy and paste the body of the pull_plough method into the Horse class. The situation can be improved somewhat using delegation to helper classes, which removes the need for duplicated code, but it is still rather more vebose and manual than would be ideal.

Java 8’s new defender methods formalize and simplify the use of delegation to implement interfaces. (Java 8 will also finally give Java closures.) This is expected to be released in early 2014.

But now it is time to move on from Java.

Ruby

Ruby offers mixins as its solution to this sort of problem.

Once again this gives us a common name Hitchable for the plough pulling behaviour, but avoids the repetition of Java’s interfaces. However, it does still have some drawbacks. Hitchable requires classes including it implement a go method, without which pull_plough won’t work. Tractor inherits such a method from Vehicle, but Horse might not. This requirement is not declared anywhere in code (though it might be documented) so the Ruby interpreter can’t warn us about a missing go method when the class is declared; only at run-time when the pull_plough method is called.

Another problem is that if future versions of the Vehicle and Hitchable mixins each implement a check_secure method with differing functionality, Tractor can only inherit one of them. The choice of which would be inherited would be made deterministically by Ruby (it would inherit the Hitchable one) but silently, so we might only notice that our tractors are not being made secure (in the vehicular sense) when subtle bugs started turning up.

The traitor gem provides some improvements in this area, but it seems to be at an early stage of development, and I personally have had difficulty making it work.

Let’s move on again.

PHP

PHP’s traits feature (introduced in PHP 5.4) offers ways around both of the above problems in the Ruby implementation.

If we added the Hitchable trait to Horse and forgot to implement go, we’d get an instant error message:

And in the case of the check_secure method mentioned above, we’d get a similar fatal error:

To resolve this error, we’d need to provide a check_secure method in the Tractor class itself to override the conflicted methods in both traits with some sort of Tractor-specific notion of security which hopefully encompasses the semantics of both traits’ methods.

The PHP trait mechanism is very good, but it’s missing one thing that Java’s interfaces and Ruby’s mixins each provide. It has no simple programmatic way of determining whether a given object $x performs the Hitchable trait.

Nor should you want one claim PHP’s developers. PHP’s traits are intended as “engine-level copy-and-paste” and nothing more. It seems a shame that the developers of this feature haven’t been more ambitious with it.

(I’ll note that the reflection API, does allow you to check whether an object uses a particular trait, but it’s not very pretty.)

Let’s continue our journey.

Perl

The Moose module for Perl offers good support for traits, though in Moose they’re usually referred to as “roles”. (Moose is not just an implementation of roles though, it provides many other features for writing concise and maintainable object-oriented Perl.)

Everything on our checklist is covered: we don’t have to copy and paste code between classes; we have a name (Hitchable) for the common behaviour; the Hitchable role can specify a list of methods it requires consuming classes to implement; we get error messages for method conflicts; and if we have an object $x there’s a simple way to check if it does theHitchable role: $x->DOES('Hitchable') returns a boolean.

It should be noted that Moose is a third-party module, and is not bundled with Perl. There are a raft of other role implementations (compatible to various degrees with Moose) freely available, including Moo::Role and Role::Tiny.

However, things are afoot! Moose’s original developer Stevan Little is currently working on a light-weight object-oriented framework with role support, with the aim for it to be included in the Perl core, perhaps as soon as May 2015.

I’ve already said that in Perl, these packages of common behaviour are usually referred to as “roles” rather than “traits” – this is because the word “trait” is often used for a more particular meaning. With Moose it is possible to apply a roles to an individual object at runtime; it is these runtime-applied roles that are referred to as traits.

Runtime application of traits is an extremely powerful technique for applying plugins to an object based on, say, the contents of a configuration file, or a JSON response from a web service.


Moose is partly inspired by Steven’s work on Perl 6, where roles are a native feature. Perl 6’s concept of roles is largely based on the concept of traits available in some dialects of Smalltalk.

Scala has an excellent implementation of traits, also inspired by Smalltalk. And like Perl, it allows traits to be added to individual objects.

Joose is a port of many of Moose’s concepts to Javascript.


Horizontal code reuse offers advantages over inheritance in many situations, and could be considered an evolution of the exhortation to “favour composition over inheritance”. However, some languages make horizontal code reuse easier than others.

Full runnable versions of the code samples shown in this article can be found on GitHub. The repository also includes several other implementations of the code using other programming languages and role implementations.

tags:

Get the O’Reilly Programming Newsletter

Weekly insight from industry insiders. Plus exclusive content and offers.