Inheritance and Interfaces in Java and UML

How can UML can be used to graphically describe the extends and implements keywords of the Java programming language? In this second article in a series introducing UML from a programmer's perspective, Stephen Palmer discusses the options.

Like this article? We recommend

Like this article? We recommend

Welcome to the second article in a series introducing UML and object modeling
from a Java programmer's perspective. In the previous article, I introduced
UML class diagrams, comparing the way classes, attributes, operations, and
associations are represented in the Unified Modeling Language (UML) and the Java
programming language. This article considers the two Is of UML class diagrams:
inheritance and interfaces.

Inheritance

In Java, we may declare that a class extends another class and
implements one or more interfaces. Let's take a look at how
we represent each of these ideas in UML class diagrams.

Extends

Here are the bare bones of three classes written in Java. The first is an
abstract class representing a payment of some sort. The other two classes each
extend the Payment class and represent two different methods of payment.

Figure 1 shows the same three classes in UML. As is often the case, details
such as types and parameters have been omitted from the operations and
attributes so that the overall structure of the classes and their relationships
shows through clearly.

The extends keyword in Java declares inheritance of both interface and
implementation. UML has an equivalent generalization relationship that is
drawn as a solid line with a closed arrowhead from the subclass to the
superclass. The additional Sale class helps illustrate the difference between
the type of arrowhead used in the UML generalization relationships and those
used in directed UML association relationships. Another difference is that,
unlike associations, generalization relationships have no need for
multiplicities or role names at the ends of the relationship.

I think you will agree that it is easier and quicker to see the inheritance
relationships between the three classes from the UML class diagram in Figure 1
than from looking at three separate Java source code files. It is also far
quicker to sketch the UML class diagram on a whiteboard or flipchart than to
type up the Java source code when discussing the design with a customer or
fellow developer.

NOTE

Some argue that they keep the class structure of a system in their head, so
they need to work only with Java source code. This is, of course, nonsense for
larger systemsand difficult for even small systems that have changes
applied by different people over a significant period of time. It also has the
drawback that there is no efficient way, short of a Vulcan mind-meld, of
ensuring that the structures contained in each team member's head are
consistent.

An abstract class in UML is identified by writing the class name in italics.
This can be almost impossible to distinguish when sketching models on flipcharts
or whiteboards. Some people recommend using a tag value of {abstract} in the
bottom-right corner of the class name compartment in these circumstances.

Personally, I find the use of {abstract} too verbose when working on a
whiteboard, so I tend to break from standard UML in this situation and just
write a 0 for zero instances in the bottom-right corner of the class name
compartment. I also use 1 in that position to indicate a singleton class (a
class that only ever has one instance) and, when necessary for clarity, I use N
to represent an enumeration (a class that has a fixed number of instances
representing things such as the days of the week or colors of the rainbow, and
so on). However, this is only my own shorthand convention for informal
whiteboard/flipchart work. It is not standard UML, and is unlikely to be
supported by any UML modeling tool.

Historical Note

UML was first devised by a team working at Rational Corporation, the producer
of the Rose UML modeling tool. UML was unveiled at OOPSLA in 1995. The UML
specification was subsequently adopted by the Object Management Group (OMG) in
1997. The OMG task force that continues to develop the UML specification quite
understandably has representation from nearly all the leading UML tool vendors.
It is, therefore, not surprising if some of the UML notation is inconvenient
when working with whiteboards and flipcharts instead of with software tools.

The Problem With Inheritance

Inheritance of the type signified by the extends keyword in Java is a very
powerful tool. It allows one class to make use of attributes and methods of
another class as if they were its own. When first introduced, inheritance of
this sort was seen as a wonderful mechanism for reusing existing code.
Unfortunately, large inheritance trees tend to be brittle, and changes in one
part of the tree can force a ripple of changes throughout the tree. This is
contrary to the principle of localizing change that underpins the idea of
encapsulation in object-oriented programming. Thankfully, the ease in which
inheritance trees can be viewed in UML also makes it easy to apply guidelines on
the use of this type of inheritance. The following guidelines are adapted from
Peter Coad's Java Design book1:

For superclass A and subclass B apply the following checks:

The phrase "B is a role played by a A" does not make sense.

B never needs to transmute to be an object in some other class.

B extends rather than overrides or nullifies the behavior of A.

A is not merely a utility class (useful functionality you want to reuse).

For a problem domain (business objects): Both A and B define the same
kind of object; either user transactions, roles, entities (party, place or
thing), or similar categorizations of other objects.

If any of the above checks fail, then it is likely to be an inappropriate use
of inheritance, and a design using associations would be more robust. For
example, Figure 2 falls foul of check 1 because "Employee is a role played
by a Person" makes sense as an English statement. It also falls foul of
check 2 because an employee would have to change class if they want to be a
customer at some point in time. A person wanting to be an employee and a
customer at the same time needs to be represented by two distinct objects,
duplicating the information in the Person class and introducing the risk of data
integrity problems between the two copies.