This is a very old article. It has been imported from older blogging software, and the formatting, images, etc may have been lost. Some links may be broken. Some of the information may no longer be correct. Opinions expressed in this article may no longer be held.
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_plough
to 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.
public interface Vehicle { public void go (); } public interface Hitchable { public void go (); public void pull_plough (); } public class Tractor implements Vehicle, Hitchable { public void go () { System.out.println("Brrrrm!"); } public void pull_plough () { System.out.println("Hitching plough"); this.go(); } }
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.
module Vehicle def go puts "Brrrrm!" end end module Hitchable def pull_plough puts "Hitching plough" self.go end end class Tractor include Vehicle include Hitchable end
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.
<?php trait Vehicle { public function go () { echo "Brrrrm!", "\n"; } } trait Hitchable { abstract public function go (); public function pull_plough () { echo "Hitching plough", "\n"; $this->go(); } } class Tractor { use Vehicle; use Hitchable; }
If we added the Hitchable
trait to Horse
and forgot to implement go
, we’d get an instant error message:
PHP Fatal error: Class Horse contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Horse::go)
And in the case of the check_secure
method mentioned above, we’d get a similar fatal error:
PHP Fatal error: Trait method check_secure has not been applied, because there are collisions with other trait methods on Tractor
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.)
package Vehicle { use Moose::Role; sub go { say "Brrrrm!"; } } package Hitchable { use Moose::Role; requires 'go'; sub pull_plough { my $self = shift; say "Hitching plough"; $self->go; } } package Tractor { use Moose; with 'Vehicle', 'Hitchable'; }
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 the Hitchable
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 Steven 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.