next up previous contents
Next: The need to change Up: Simple type systems are Previous: Simple type systems are

The need to change return types in subclasses

In our first example we show that it is useful to be able to modify the return type of methods when they are redefined in subclasses.

Many object-oriented languages include a method for making a shallow copy of an object. A shallow copy is made by copying the values of instance variables. If the instance variables hold references to other objects, only the references are copied, not the objects being referred to. Thus if this shallow clone method (call it ${\it {ShallowClone}}$)is applied to the head of a linked list, only the head node is copied while the rest of the list is shared between the new and old lists. ${\it {ShallowClone}}$ is often available as a method in all classes (e.g., it is often provided by a ${\it {Top}}$ class, which is implicitly a superclass of all other classes).

Often it is desirable to write a ${\it {DeepClone}}$ method which is based on ${\it {ShallowClone}}$. One typically first writes code to send the ${\it {ShallowClone}}$ message to self to make the shallow copy, and then code to clone all objects held in the instance variables.

Suppose we have a class ${\it {C}}$ that includes a method ${\it {DeepClone}}$, which returns an object of type ${\it {CType}}$. See Figure 6. Suppose we now define a subclass ${\it {SC}}$ of ${\it {C}}$ which includes new methods as well as a new instance variable holding an object. Then ${\it {DeepClone}}$should be redefined to clone the contents of this new instance variable after all of the code in the original ${\it {DeepClone}}$ from ${\it {C}}$ has been executed.


  
Figure 6: Typing DeepClone methods in subclasses.
\begin{figure*}
\begin{verbatim}
class C
 var
 ...
 methods
 ...
 function DeepC...
 ...- method not contained in C
 begin ... end
end class;\end{verbatim}\end{figure*}

Unfortunately, the rules of the simple type systems require that ${\it {DeepClone}}$ for ${\it {SC}}$ to also return a ${\it {CType}}$, just as in ${\it {C}}$, even though it is obvious that it actually returns an object of type ${\it {SCType}}$. While this is not type-unsafe, it represents an unnecessary loss of information in the type system. If we write ${\it {anSC.DeepClone().newMeth()}}$ for ${\it {anSC}}$ of type ${\it {SCType}}$, the type checker will complain, even though the object resulting from ${\it {anSC.DeepClone()}}$ has a method ${\it {newMeth}}$.

In these circumstances, Object Pascal, C++, and Java programmers would normally be forced to perform a type cast to tell the compiler that the cloned object has the type ${\it {SCType}}$. In the case of Object Pascal and C++, the type cast is unchecked. In Java, it would be checked at run-time. Modula-3 programmers would use a typecase statement which also performs a run-time check to get the same effect.

One could attempt working around these deficiencies in the static type system by making up a new name for the revised ${\it {DeepClone}}$ method (e.g., ${\it {SCDeepClone}}$). Unfortunately this would mean that inherited methods that included a message send of ${\it {DeepClone}}$ would call the old ${\it {DeepClone}}$ for ${\it {C}}$ rather than the updated method from ${\it {SC}}$ actually desired. As a result the value in the new instance variable will not be cloned, possibly causing problems later in the program. Thus the restriction on changing types of methods in subclasses gets in the way of the programmer, even though there should be no real typing problem. Not surprisingly, we have similar problems even writing down the type of the built-in ${\it {ShallowClone}}$. In Object Pascal, ${\it {ShallowClone}}$ is simply given a type indicating that it returns an element of the ${\it {Top}}$ type. It must then be cast to the appropriate type.


next up previous contents
Next: The need to change Up: Simple type systems are Previous: Simple type systems are
Kim Bruce
10/28/1998