Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding return type in extended interface - Bad idea?

Tags:

java

oop

In Java, you can do the following :

public interface IEngine{}
public interface ICoolEngine extends IEngine{}

public interface Car
{
   IEngine getEngine();
}
public interface ICoolCar extends ICar
{
    @Override
    ICoolEngine getEngine();
}

While this nicely solves a problem I've been grappling with, something about it "feels" wrong.

Am I committing some nasty design faux pas here?

like image 895
Marty Pitt Avatar asked May 14 '09 17:05

Marty Pitt


3 Answers

No, you are doing the right thing. Covariant returns just specify that the class, and classes below it, must return a specific subclass of the original general class argument that the parent class returned. It also means that your subclasses are still compatible with the original interface that requires that it return an Engine, but if you know that it is an ICoolCar, that it has an ICoolEngine - because the more specific interface knows of more specific functionality. This applies to interfaces as well as classes - this is correct, proper and useful to boot.

like image 168
MetroidFan2002 Avatar answered Oct 30 '22 16:10

MetroidFan2002


No, that's fine. Since ICoolEngine extends IEngine, any object implementing ICoolEngine can be treated as if it's an IEngine (without all the ICoolEngine-specific methods of course). You'll just have to be aware of the type difference depending on which interface you are working with in each situation, and make sure not to use ICoolEngine methods that aren't defined in IEngine (assuming that, in your actual code, there are additional methods listed in the equivalent of ICoolEngine).

It's not a bad practice to do this; you're simply using the power of polymorphism.

like image 3
Marc W Avatar answered Oct 30 '22 15:10

Marc W


Covariant return types is a deliberate feature that was added in 1.5 (to support generics primarily).

@Override may not work for overriding abstract methods with some compilers (javac was updated in 1.6, but the JLS amendment was missed out).

As always adding an method to an interface risks compatibility issues. Redeclaring a method exactly as in the super-type would be fine, but changing the return type causes a bridge method in implementation classes. This is why Iterable.iterator does not return a read-only version of the Iterator interface.

like image 2
Tom Hawtin - tackline Avatar answered Oct 30 '22 14:10

Tom Hawtin - tackline