Why can't parameter types be loosened in overridden methods?

This code is invalid:

interface Foo
{
    public void foo(final String string);
}

public class Bar implements Foo
{
    // Error: does not override.
    @Override public void foo(final Object object)
    {
    }
}

Because every String is obviously an Object, I would expect this code to be perfectly fine: any code that depends on giving foo() a String would stil function when foo() actually takes an Object.

It appears, though, that method signatures have to be identical to those of the methods they're overriding. Why?

Answers


What if

interface Foo
{
    void foo(String string);
    void foo(Object string);
}

Then which method is overridden by Bar?


'loosening' as you put it should not impact on someone expecting to use your interface defined method in a particular way, as any methods you call on that object should in theory be callable on the specified object, but Eugene's point stands, becaause there would probably be a little compiler headache to deal with in determining what method you actually intended to override if you just vaguely want to stick to the interfaces specification. Also, why whould this be desireable if you are going to stick to moving up the inheritance heirarchy, because surelely you will be able to do all you want to the thing further down the hierarchy as to 'Object' for example? Possibly casting inside your method would solve your problem? If it is possible to do what you want to do, you will also probably start treading on the polymorphism paradigm.


I think this is a classical contravariance issue. Your interface requires a string to be passed as parameter, you want an implementation that accepts an object (because, after all, strings are also objects).

The problem is that if you allowed that, then you could no longer guarantee that the parameter being required by the interface is a string or any one of its ancestors. You might just as well pass any object to your implementation and you would be breaking the contract of the interface, putting in danger the type safety and type coherence of your design.

You do have options, though:

public class Bar implements Foo
{

    @Override public void foo(final String object)
    {
    }

    public void foo(final Object object)
    {
       foo((String) object);
    }
}

By this, you would be ensuring that object is actually a string, making possible to the type system to check that you are actually complying with the interface contract established in the method signature.

Is there a particular scenario in which you would consider your contravariance example to be requirement?


It's just the constructs of the Java programming language. The structure of Java programs will grow on you. So for now just try and adjust.


Need Your Help

In a Firefox extension, how can I copy rich text/links to the clipboard?

firefox firefox-addon xul

Specifically, I want to copy a link (with text and location) and then to be able to paste it, e.g., into Word as a link.

Patterns : Java class conversion from axis objects

java axis

I use a axis to auto-generate webservice artifacts which I then convert into objects used within our application. Is there a sensible pattern for doing this ? We have written transform methods to o...