The Problem
It is a central tenet of object-oriented analysis and design that subtype polymorphism, which is implemented in most OO languages via inheritance, should be used to model object types which are subsets of each other; this is commonly referred to as the is-a relationship. In the present example, the set of circles is a subset of the set of ellipses; circles can be defined as ellipses whose major and minor axes are the same length. Thus, code written in an OOPL which models shapes will frequently choose to make class Circle
as a sub-class of class Ellipse
(i.e., inheriting from it).
If the classes are immutable, there is no problem with this state of affairs. Circles satisfy all invariants of ellipses; and an (immutable) circle can be used in any context where an immutable ellipse is expected. The relationship satisfies the Liskov substitution principle. Ellipse
could have a method stretchX (integer Factor)
which alters the length of one of its axes, but not the other, and returns the result in a new Ellipse
object. This would cause no problem for Circle.stretchX
, as it could return a new Ellipse
just as the Ellipse.stretchX
does (whilst remaining unaltered itself).
But some OO designs encourage the use of mutators, methods which modify instances of the class. A sub-class has to provide support for all behaviour supported by the super-class; subclasses must implement any mutators defined in a base class. In the present case, the method Ellipse.stretchX
alters the length of one of its axes in place. If Circle
inherits from Ellipse
, it must also have a method stretchX
, but the result of this method would be to change a circle into something which is no longer a circle. The Circle class cannot simultaneously satisfy its own invariant and the behavioural requirements of the Ellipse.stretchX
method.
A related problem with this inheritance arises when we consider the implementation. An ellipse requires more state to describe than a circle does, as the former needs attributes to specify the length and rotation of the major and minor axes; whereas a circle needs only a radius. It may be possible to avoid this if the language (such as Eiffel) makes constant values of a class, functions without arguments and data members interchangeable.
Some authors have suggested reversing the relationship between circle and ellipse, on the grounds that an ellipse is a circle with additional capabilities. Unfortunately, ellipses fail to satisfy many of the invariants of circles; if Circle
has a method radius
, Ellipse
will now have to provide it as well.
The problem is sometimes expressed in statements such as "a Circle
is not a sort of Ellipse
". This looks confusingly like the absurd "a circle is not a sort of ellipse", and sounds identical, so it is unhelpful. What is actually meant is "an OO-model of a circle should not be a sort of OO-model of an ellipse"
Read more about this topic: Circle-ellipse Problem
Famous quotes containing the word problem:
“The thinking person has the strange characteristic to like to create a fantasy in the place of the unsolved problem, a fantasy that stays with the person even when the problem has been solved and truth made its appearance.”
—Johann Wolfgang Von Goethe (17491832)
“But a problem occurs about nothing. For that from which something is made is a cause of the thing made from it; and, necessarily, every cause contributes some assistance to the effects existence.”
—Anselm of Canterbury (10331109)