Is the isSubstitutable
property meant to specify that a class and its generalisation comply with the Liskov Substitution Principle (LSP)? If not, is there an easy way to specify LSP compliance of a generalisation or a generalization set?
Indeed, the LSP is defined as follows (wikipedia):
if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program
The original definition is slightly different but the principle is about instances, thus excluding the creation/construction of new instances of the constraint, as explained in Liskov&Wing's foundational article:
Objects come into existence and get their initial values through creators. Unlike other kinds of methods, creators do not belong to particular objects, but rather are independent operations.
But in the UML specs isSubstitutable
is defined based on the classifiers rather than the instances:
Indicates whether the specific Classifier can be used wherever the general Classifier can be used. If true, the execution traces of the specific Classifier shall be a superset of the execution traces of the general Classifier. If false, there is no such constraint on execution traces. If unset, the modeler has not stated whether there is such a constraint or not.
This would make isSubstitutable
a lot less useful, as it seems to imply that if the generalisation and the specialisation would have different constructors (which is often the case), they would not be substitutable. Do I read the UML specs too literally and missed a point somewhere?
Short answer. If isSubstitutable = true
for a generalization on a UML class diagram, then The Liskov Substitution Principle (LSP) is intended to be fulfilled.
A similar topic was discussed on the Sparx Systems Forum.
Some details:
While the UML definition does not refer to the instances, but to classifiers, the following elements provide context that makes clear that this is a wording issue and the property is about substitutability of instances:
The description of the Generalization is about instances:
A Generalization is a taxonomic relationship between a more general Classifier and a more specific Classifier. Each instance of the specific Classifier is also an instance of the general Classifier. The specific Classifier inherits the features of the more general Classifier. A Generalization is owned by the specific Classifier.
The purpose of isSubstitutable
is introduced in the section about generalizations, with a sentence referring explicitly to instances. This is an important context to take into account when considering the definition of that property:
If one Classifier (the parent) generalizes another (the child) it is not necessarily the case that instances of the child are substitutable for instances of the parent under every possible circumstance. (...) The isSubstitutable property may be used to indicate whether the specific Classifier can be used in every circumstance that the general Classifier can be used.
If the generalisation and the specialisation have different constructors, they can be substitutable. This is a logical consequence of the the substitutability being meant for the instances. Moreover, the example in the UML specs of the Ellipse
and the Circle
(a circle is a special case of an ellipse) is a case that illustrates this implicitly. You can pass a Circle
instance to a method that accepts an Ellipse
instance and it will continue to work correctly. The constructors of the Ellipse
and Circle
will have different constructors (the Ellipse
has 2 focuses in the constructor, the Circle
has one, since both of its focuses coincide).