Géry Ogam
Géry Ogam

Reputation: 8027

What is the relationship corresponding to implementation inheritance in UML?

What is the relationship corresponding to implementation inheritance (realized with private inheritance in C++) in the current UML specification (2.5.1, December 2017)?

Not to be confused with interface inheritance (subtyping) which corresponds in UML to the interface realization relationship denoted by a dashed line and hollow triangle, nor with implementation and interface inheritance (subclassing) which corresponds in UML to the generalization relationship denoted by a solid line and hollow triangle.

Note. — The book Design Patterns by Erich Gamma et al. published in 1994 (before UML) whose class diagrams are based on OMT (an ancestor of UML) used informally a solid line and hollow triangle with an “(implementation)” modifier for denoting implementation inheritance:

Class adapter

Figure. — OMT class diagram of the class Adapter design pattern.

Upvotes: 2

Views: 512

Answers (1)

Christophe
Christophe

Reputation: 73366

GoF terminology

GoF proposes some terminology (p. 13-15) which you seem to have adopted:

  • an object packages data (its state) and procedures (its methods) that are the only way to access the data (state encapsulation).
  • the interface to an object is the set of its methods’ signatures.
  • a type is the name of a particular interface.
  • a subtype is a type that is a superset of another type.
  • a supertype is a type that is a subset of another type.
  • the implementation of an object is the set of its state and methods’ implementations.
  • a class defines an object’s interface and implementation.
  • a subclass defines a class that is a superset of another class.
  • a superclass defines a class that is a subset of another class.
  • inheritance in this understanding corresponds to reusing an implementation.

This understanding is driven by reuse, the main topic of their book: types are just reuse of an interface, whereas classes are reuse of an implementation. This view is reductionist:

  • Nothing is said about the promises and expectations behind an interface (e.g. that I can only pop() from the stack if I have push()ed something on it first). It is just about the ability to accept the requests defined by the interface.
  • The distinction between an abstract class (which defines an interface without providing an implementation) and an interface is not at all clarified.

The last point is perfectly illustrated in your graphical example.

  • In the GoF narrative, Target and Adaptee are both defined as interface (see p. 141, section "participants"), whereas Adapter implements these interfaces.
  • Yet, in the schema, Target is represented as an abstract class (see p. 365) and Adapter’s Request() is implemented by calling SpecificRequest() but it is not shown that Adapter must implement SpecificRequest() as well.
  • Finally, GoF explains that Adapter is a subclass of Adaptee, which seems somewhat inconsistent.

UML perspective

The UML definition of an interface is much closer to what Liskov would call a type:

An Interface […] represents a declaration of a set of public Features and obligations that together constitute a coherent service. An Interface specifies a contract […]. The obligations associated with an Interface are in the form of constraints (such as pre- and postconditions) or protocol specifications, which may impose ordering restrictions on interactions through the Interface. Interfaces may not be instantiated. Instead, an Interface specification is implemented or realized […].

Classes define sets of features, may implement interfaces and can be instantiated.

What you call interface inheritance is ambiguous:

  • If you mean a class that implements the interface, it is interface realization, denoted by a dotted line with a hollow triangle on the side of the interface to be realized.
  • If you mean an interface that inherits another interface (subtyping), it is interface specialization, denoted by a plain line with a hollow triangle on the side of the more general interface.

What you call implementation and interface inheritance is ambiguous, since it is not clear if inheritance applies only to interface or also to implementation:

  • If you mean the implementation of an existing interface with a class, it is interface realization with a dotted line with a hollow triangle on the side of the interface to be realized.
  • If you mean the simultaneous inheritance of both an interface and their implementation, then it is class specialization, denoted by a plain line with a hollow triangle on the side of the more general class.

If with implementation inheritance you were thinking of inheriting the implementation without inheriting the interface, i.e. private inheritance, then there is nothing special foreseen in UML, and you have to translate your implementation intent into UML concepts, as explained for example in this SO question.

Now to illustrate the graphical notation, here is the class Adapter pattern as described in GoF using the participant roles:

enter image description here

And here is a more logic diagram, if considering that Adaptee is in reality an existing implementation that needs to be adapted:

enter image description here

Upvotes: 4

Related Questions