Site Map  Search

OOA Home OOD content UML Corrections book Code object Exercise Solutions oriented Resources tutorial Miscellany textbook

Exercise Solutions (Restricted)

Chapters 1 2 3 4 5 6 7 8 9 11 12

Chapter 12

 

Question 12.3
Produce a revised version of the sequence diagram from Exercise 11.5 in which the interface type Appointment is used appropriately, loosening the coupling.

Exercise 11.3 Sequence Diagram

Question 12.4
In the section on bidirectional many-to-many associations (Figure 12.42), there was a Crime and Suspect example where an artificial intersection object was chosen to help us out. From your, theoretical of course, knowledge of the subject matter, how many better objects can you come up with?

  • Participation
  • Collusion
  • Perpetration

 

Question 12.6
“A newcomer to object-oriented programming might confuse possession with access when considering inheritance of instance variables.” Discuss.

When first encountering the concepts of inheritance (and there is certainly more than one concept to be grasped and, hence this discussion, tricky to grasp properly), one can form the incorrect impression that there will be an object of the subclass (derived class) somehow linked to an instance of the superclass (base class). That's not how it works though. Instead of two instances being linked, it is the classes that are linked, and together they produce a single object instance. (Indeed, that's two of the problems with inheritance: object encapsulation is removed rather than strengthened; and inheritance must affect the entire set of instances and is a compile time choice rather than a run-time, perhaps pluggable, choice.) So, if there is just one instance, and it's an instance that is likely to be seen as a subclass instance, one must ensure that one is clear as to what state, what instance variables, it will have available to it.

One must realize that, under the normal polymorphic kind of inheritance (public inheritance in C++), an object might receive a message that binds to a method that is an inherited method, and the said inherited method is very likely to expect and depend of the presence of superclass instance variables that must therefore have also been inherited as well.

If the inheritance mechanism required that a class using it made superclass instance variables automatically public, we would surely have stopped using inheritance altogether, many years ago. No; we must simply require that superclass instance variables are always present in subclass instances, whatever their access categories.

So what does private mean for an inherited instance variable? It means that it can only be accessed by superclass methods. Inherited variables are available only to inherited code. So some class encapsulation is at least kept, even if instance encapsulation (which in contrast, composition-delegation preserves) is lost.

 

Question 12.x
Why would I hope that any modern object-oriented programming style guide would discuss the correct use of abstract and final (or sealed) keywords in class definitions? And what do you think it would say?

[This exercise was inexplicably omitted in the first printing of the first edition. JD]

Today's languages, assuming they even have these keywords, are a bit timid as far as using them in sensible default ways. So it's important that style guides discuss the issues.

Textbooks frequently get this area wrong and don't use the keywords.

Not all languages have all the necessary mechanisms provided via keywords (C++ for example), so it's important to discuss how to get the same effect via idioms and patterns.

As discussed in the answer to question 12.8, it's very important that base classes aren't instantiated. Correctly doing two jobs (providing default implementation and transmitting type) with one relationship is difficult enough; doing three (adding instantiation) is close to impossible. So if a language has the abstract keyword (or its equivalent) to prevent a class from being instantiated, even when it has no abstract methods, then that keyword should be the default for all superclasses.

It's also very important that concrete classes don't become superclasses later in their careers. Otherwise some perfectly happy class is going to become a fragile superclass; and you will almost certainly have to carry on instantiating it, and thus break the rule about instantiating superclasses. So if a language has the final keyword (or its equivalent) to prevent a class from being subclassed, then that keyword should be the default for all concrete classes.

 

Question 12.10
Between Figure 12.43 and Figure 12.47 the name Officer changed to the implementation class name UniformedOfficer. Revise and describe the general principle being illustrated here.

Type names should be as specific as they need to be, and no more specific than that; concrete class names shouldn't intrude into the space for future concrete class names.

When some piece of moderately strongly typed code declares a parameter, a return or a variable, it should be saying something like, "I need, in this resource here, something that is no less than an Asset, and no more than an Asset." To have used InvoicedCustomerThatOwesMeMoney when only Asset was required is closing the door to future flexibility. One is only programming in the present tense, and as Larry Wall I think said, one should program in the future tense.

When one is fabricating a concrete class, on the other hand, one is coming up with just one way of implementing a type. There will be other ways. If one uses up the the name Officer, one will regret that when one comes up with plain-clothes officer and realizes that the original officer was a UniformedOfficer. Concrete classes should have narrow focused names that leave room for other ways of making objects in the future.

Question 12.11
(Difficult) Speculate as to:
a) why I didn’t use Crime and Location for the example of a directed characterizing inter-instance (“association”) relationship in Figure 12.37. (Hint: this continues the theme of the previous exercise.)

Because I would have had an association emerging from a generally named thing that was probably an interface; and associations should not emerge from interfaces (interfaces or pABCs).

b) the purpose that the :name labels are serving in Figure 12.39 and why I would have felt uncomfortably about an example that omitted them.

This is almost same thing: associations typed with class names, especially concrete class names are not very flexible.

 

Question 12.13
In the discussion of Figure 12.93, I initially wrote, “Perhaps an insightful factoring scheme can obviate storing the name instance variable in so many places.” Why was that silly; why did I rephrase it, “Perhaps an insightful factoring scheme can obviate defining the name instance variable in so many places?”

It wouldn’t make any difference as to whether one defined an instance variable in a subclass or its superclass; subclass instances would always store, i.e. possess, just one copy of an instance variable, whether it was defined in the subclass or in the subclass' superclass.

[Languages vary as to what would happen if one did something completely silly by defining the same instance variable in both a subclass and its superclass. JD]