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 )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. is often available as a method in all classes (e.g., it is often provided by a class, which is implicitly a superclass of all other classes).
Often it is desirable to write a method which is based on . One typically first writes code to send the 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 that includes a method , which returns an object of type . See Figure 6. Suppose we now define a subclass of which includes new methods as well as a new instance variable holding an object. Then should be redefined to clone the contents of this new instance variable after all of the code in the original from has been executed.
Unfortunately, the rules of the simple type systems require that for to also return a , just as in , even though it is obvious that it actually returns an object of type . While this is not type-unsafe, it represents an unnecessary loss of information in the type system. If we write for of type , the type checker will complain, even though the object resulting from has a method .
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 . 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 method (e.g., ). Unfortunately this would mean that inherited methods that included a message send of would call the old for rather than the updated method from 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 . In Object Pascal, is simply given a type indicating that it returns an element of the type. It must then be cast to the appropriate type.