Figure 23.10 presents an updated class diagram of our model that incorporates inheritance and introduces class Transaction
. We model an association between class ATM
and class Transaction
to show that the ATM
, at any given moment, either is executing a transaction or is not (i.e., zero or one objects of type Transaction
exist in the system at a time). Because a Withdrawal
is a type of Transaction
, we no longer draw an association line directly between class ATM
and class Withdrawal
—derived class Withdrawal
inherits base class Transaction
’s association with class ATM
. Derived classes BalanceInquiry
and Deposit
also inherit this association, which replaces the previously omitted associations between classes BalanceInquiry
and Deposit
and class ATM
. Note again the use of triangular hollow arrowheads to indicate the specializations of class Transaction
, as indicated in Fig. 23.9.
We also add an association between class Transaction
and the BankDatabase
(Fig. 23.10). All Transaction
s require a reference to the BankDatabase
so they can access and modify account information. Each Transaction
derived class inherits this reference, so we no longer model the association between class Withdrawal
and the BankDatabase
. The association between class Transaction
and the BankDatabase
replaces the previously omitted associations between classes BalanceInquiry
and Deposit
and the BankDatabase
.
We include an association between class Transaction
and the Screen
because all Transaction
s display output to the user via the Screen
. Each derived class inherits this association. Therefore, we no longer include the association previously modeled between Withdrawal
and the Screen
. Class Withdrawal
still participates in associations with the CashDispenser
and the Keypad
. We do not move these associations to base class Transaction
, because the association with the Keypad
applies only to classes Withdrawal
and Deposit
, and the association with the CashDispenser
applies only to class Withdrawal
.
Our class diagram incorporating inheritance (Fig. 23.10) also models Deposit
and BalanceInquiry
. We show associations between Deposit
and both the DepositSlot
and the Keypad
. BalanceInquiry
takes part in no associations other than those inherited from class Transaction
—a BalanceInquiry
interacts only with the BankDatabase
and the Screen
.
Figure 23.1 showed attributes and operations with visibility markers. Now we present a modified class diagram in Fig. 23.11 that includes abstract base class Transaction
. This abbreviated diagram does not show inheritance relationships (these appear in Fig. 23.10), but instead shows the attributes and operations after we’ve employed inheritance in our system. Abstract class name Transaction
and abstract operation name execute
in class Transaction
appear in italics. To save space, we do not include those attributes shown by associations in Fig. 23.10—we do, however, include them in the C++ implementation. We also omit all operation parameters, as we did in Fig. 23.1—incorporating inheritance does not affect the parameters already modeled in Figs. 22.18–22.21.
Software Engineering Observation 23.2
A complete class diagram shows all the associations among classes and all the attributes and operations for each class. When the number of class attributes, operations and associations is substantial (as in Fig. 23.10 and Fig. 23.11), a good practice that promotes readability is to divide this information between two class diagrams—one focusing on associations and the other on attributes and operations. However, when examining classes modeled in this fashion, it’s crucial to consider both class diagrams to get a complete view of the classes. For example, one must refer to Fig. 23.10 to observe the inheritance relationship between Transaction and its derived classes that is omitted from Fig. 23.11.