Covariant Return Types

Let's say that we are designing a programming language and we want type safety. One of the places that type safety crops up is in the area of method returns. If I have a method named clone, for instance, and it returns a reference to Object, everything is fine as anyone who gets the returned object expects it to be an Object, nothing more:

        // this example is not in Java, but I hijack the syntax..

Object aClone = aThing.clone ();

The only problem is that a message like clone is bound to be very useful, so useful that you'd probably want a bunch of different object types to be able to respond to it in their own unique way. So you subclass and override clone:

        class Classy extends Object
        {
            public Object clone () {
                ...
            }
        }

But, then you have to:

        Classy aCopy   = (Classy)aClassyThing.clone ();

Why? Because the return type of clone is Object, so all of the overrides have to return Object also. This is known as invariance.

But, is it necessary?

What if the language allowed this:

        class Classy extends Object
        {
            // this clone overrides Object Object.clone ()
            public Classy clone () {
                ...
            }
        }

Classy aClassyThing = new Classy (); Classy aCopy = aClassyThing.clone ();

By the way..

        Object aThing = aClassyThing;
        Object aCopy = aThing.clone ();

would call the same clone: the one for Classy. Why? Because the object itself knows how to respond to clone. All the compiler has to do is permit the assignment when it can be determined to be safe. Assigning to a more general type reference is always safe.

These are CovariantReturnTypes. The name comes from the fact that the type of the return is allowed to vary in the same direction that you subclass.


See: WideParameterNarrowReturn


EditText of this page (last edited May 14, 2004) or FindPage with title or text search