When not to use tuple subclassing
Factor handbook » The language » Objects » Tuples » Tuple subclassing

Prev:Tuple subclassing example
Next:final


Tuple subclassing should only be used for is-a relationships; for example, a car is a vehicle, and a circle is a shape.

Anti-pattern #1: subclassing for has-a
Subclassing should not be used for has-a relationships. For example, if a shape has a color, then shape should not subclass color. Using tuple subclassing in inappropriate situations leads to code which is more brittle and less flexible than it should be.

For example, suppose that shape inherits from color:
TUPLE: color r g b ; TUPLE: shape < color ... ;

Now, the implementation of shape depends on a specific representation of colors as RGB colors. If a new generic color protocol is devised which also allows HSB and YUV colors to be used, the shape class will not be able to take advantage of them without changes. A better approach is to store the color in a slot:
TUPLE: rgb-color r g b ; TUPLE: hsv-color h s v ; ... TUPLE: shape color ... ;

The delegate library provides a language abstraction for expressing has-a relationships.

Anti-pattern #2: subclassing for implementation sharing only
Tuple subclassing purely for sharing implementations of methods is not a good idea either. If a class A is a subclass of a class B, then instances of A should be usable anywhere that an instance of B is. If this property does not hold, then subclassing should not be used.

There are two alternatives which are preferred to subclassing in this case. The first is Mixin classes.

The second is to use ad-hoc slot polymorphism. If two classes define a slot with the same name, then code which uses Slot accessors can operate on instances of both objects, assuming the values stored in that slot implement a common protocol. This allows code to be shared without creating contrived relationships between classes.

Anti-pattern #3: subclassing to override a method definition
While method overriding is a very powerful tool, improper use can cause tight coupling of code and lead to difficulty in testing and refactoring. Subclassing should not be used as a means of "monkey patching" methods to fix bugs and add features. Only subclass from classes which were designed to be inherited from, and when writing classes of your own which are intended to be subclassed, clearly document what subclasses may and may not do. This includes construction policy; document whether subclasses should use new, boa, or a custom parameterized constructor.

See also
Parameterized constructors