1

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?

TylerH
  • 20,799
  • 66
  • 75
  • 101
Maxpm
  • 24,113
  • 33
  • 111
  • 170
  • 1
    This [question](http://stackoverflow.com/questions/2995926/why-is-there-no-parameter-contra-variance-for-overriding) seems related... – Jordão Apr 09 '12 at 01:04

4 Answers4

4

What if

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

Then which method is overridden by Bar?

Eugene Retunsky
  • 13,009
  • 4
  • 52
  • 55
  • The second one, obviously. I'm sorry; I'm missing the point. – Maxpm Apr 09 '12 at 01:06
  • Let's assume compiler accepts constructions like you did in your example. But now you added a method `void foo(Object object);` to the Foo class. And `Bar.foo` now overrides it, instead of `void foo(String string);`. It will just break the whole code and lead to unpredictable results. – Eugene Retunsky Apr 09 '12 at 01:58
0

'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.

Laurence
  • 1,556
  • 10
  • 13
0

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?

Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
0

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.

Brian
  • 31
  • 6