Every once in a while, I learn a new fact that reminds me to stay humble with my knowledge of Java.
As you know, to implement a method defined in an interface, you are supposed to provide a method with the same signature.
Let’s take:
public interface Test { Collection getSomething(); }
If you implement it in this way:
public class TestImpl implements Test { public Object getSomething() { return null; } }
You’ll get a compiler error, as the return type is not compatible. So the right way it to write:
public class TestImpl implements Test { public Collection getSomething() { return null; } }
Nothing special here.
Now, what about the other way round? Something like this?
public interface Test { Object getSomething(); }public class TestImpl implements Test { public Collection getSomething() { return null; } }
Incredibly, this works perfectly, both at compiler and runtime.
Of course, once you think about it, it makes perfect sense. The signature remains compatible, since your new method is still returning an Object, albeit a specific one.
Still, it is surprising. Well, to me at least. It is something that we are not *told*! ;-)
Interesting, but does it work only for the return type? i guess so!
anyway i tried it in dotnet and it doesnt work…
Well, clearly, it would not be able to give a more specialize type for the parameters in an implementation, as you could get an invalid parameter type. So you cannot declare
void setSomething(Object obj);
in an interface and implement it with
void setSomething(String str) {…}
as you would be running the risk of getting something not compatible with String.
However, the opposite would be interesting. Say you declare
void setSomething(String str);
if you implement it with
void setSomething(Object obj) {…}
well, it *could* work! Except that it doesn’t, of course. The compiler flags it.
Regarding .NET, I’m a bit surprised that you cannot generalize the return type. It could mean that .NET is treating the method signature a bit differently than Java does. If I recall, the definition of a method signature in Java only contains the name and the parameters, but not the return type (or the throws declaration).
I don’t think that this worked before JDK5