next up previous
Next: 1.7.3 Interface Types Up: 1.7 Interfaces Previous: 1.7.1 Multiple Inheritance

1.7.2 Implicit Polymorphism

A cardinal rule in program design is ``Never repeat code''. If a program repeats essentially the same code in two or more places, then the programmer failed to identify a common abstraction that should only be written once. The repeated code sections can be replaced by calls on a new abstraction that defines the repeated operation. Any minor differences between the repeating code sections can be accommodated by passing appropriate arguments that ``fill in'' the differing expressions.

This ``code factoring'' technique works extremely well in functional languages where code is readily treated as data. It is equally applicable to Java but the notational details may be cumbersome in some cases because methods cannot be directly passed as arguments. In addition, since Java is statically typed, code factoring may introduce some imprecision is program typing.

Passing methods as arguments is such an important programming technique that object-oriented programmers have developed a design pattern, called the command pattern, that enables Java programs to indirectly pass methods as parameters by embedding them in ``dummy'' objects called commands. This pattern is discussed in the next subsection. The complicating effects of Java's static type discipline are illustrated by the following example.

Consider a program that manipulates lists of several different types of elements. One approach is to define a separate composite class hierarchy for each kind of list. But this approach requires replicating essentially the same code in the definition of each class. To avoid this code replication, we can define a single composite class hierarchy for lists of type Object. Since all Java object types are subtypes of Object, such a list type can be used in place of any specific list type. However, when we extract an element from such a list, we will generally have to cast it to the specific type required by the context in which it is used. These casting operations clutter the code and reduce the precision of static type checking. Nevertheless, the advantages conferred by avoiding code replication usually outweigh these disadvantages.


Finger Exercise Load the sample IntList1 program into the DrJava Definitions pane. Convert it to a definition of a class ObjectList where the list elements have type Object instead of type int. Test this program and save it in a file objectList.java for future use.


Finger Exercise Load the program in your saved file objectList.java into the Definitions pane. Define a method

ObjectList sort()
that sorts a list of Integer into non-descending order, akin to the sort method on IntList that you defined in section 1.6. Your code will need to use casting operations confirming that the elements in the receiver of a sort invocation have type Integer. Test your code. What happens if you try to sort a list containing elements that are not of type Integer?



next up previous
Next: 1.7.3 Interface Types Up: 1.7 Interfaces Previous: 1.7.1 Multiple Inheritance
Corky Cartwright 2003-07-07