Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在扩展接口中重写返回类型-坏主意?_Java_Oop - Fatal编程技术网

Java 在扩展接口中重写返回类型-坏主意?

Java 在扩展接口中重写返回类型-坏主意?,java,oop,Java,Oop,在Java中,您可以执行以下操作: public interface IEngine{} public interface ICoolEngine extends IEngine{} public interface Car { IEngine getEngine(); } public interface ICoolCar extends ICar { @Override ICoolEngine getEngine(); } 虽然这很好地解决了我一直在努力解决的一个问

在Java中,您可以执行以下操作:

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

public interface Car
{
   IEngine getEngine();
}
public interface ICoolCar extends ICar
{
    @Override
    ICoolEngine getEngine();
}
虽然这很好地解决了我一直在努力解决的一个问题,但它“感觉”有些不对劲


我在这里犯了一些令人讨厌的设计错误吗?

不,没关系。由于
ICoolEngine
扩展了
IEngine
,因此实现
ICoolEngine
的任何对象都可以被视为
IEngine
(当然没有所有的
ICoolEngine
特定方法)。您只需根据在每种情况下使用的接口了解类型差异,并确保不要使用未在
IEngine
中定义的
ICooEngine
方法(假设在您的实际代码中,存在与
ICooEngine
等效的其他方法)


这样做并不是一个坏习惯;你只是在利用多态性的力量。

不,你做的事情是正确的。协变返回只指定类及其下的类必须返回父类返回的原始通用类参数的特定子类。这也意味着您的子类仍然与要求它返回引擎的原始接口兼容,但是如果您知道它是一个ICoolCar,那么它就有一个ICoolEngine——因为更具体的接口知道更具体的功能。这适用于接口和类-这是正确的、适当的,对引导非常有用。

协变返回类型是1.5中添加的一项经过深思熟虑的功能(主要用于支持泛型)

@覆盖可能不适用于覆盖某些编译器的抽象方法(javac在1.6中进行了更新,但JLS修订被遗漏)


像往常一样,向接口添加方法会带来兼容性问题的风险。完全像在超级类型中那样重新定义方法是可以的,但是更改返回类型会导致实现类中出现桥接方法。这就是为什么
Iterable.iterator
不会返回
iterator
接口的只读版本。

您所做的完全正常

我更愿意这样说:

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

public interface ICar<T extends IEngine> {
   T getEngine();
}

public interface ICoolCar extends ICar<ICoolEngine> { }
公共接口IEngine{}
公共接口ICooEngine扩展了IEEngine{}
公共接口ICar{
T getEngine();
}
公共接口ICoolCar扩展ICar{}

我使用泛型是因为当您使用注释时,我猜您正在使用Java 5+

我不会对这个答案投反对票,因为它很有趣。然而,我不能说我喜欢它,因为它似乎只是为了使用泛型而使用泛型,而根本不需要使用泛型。ICoolCar接口的两个通用实现存在歧义,这一事实说明了这一点——泛型为这一点增加了不必要的复杂性。最初的定义清楚地表明,它返回了ICooEngine的一个实例-不需要泛型,也没有歧义。另外,Java 5中添加了协变类型,因此整个问题无论如何都没有意义。如果需要接口实现来指定“getEngine()”返回类型,我的解决方案会更好。我在编写GenericDao时使用了类似的方法,它的实现需要指定许多方法的返回类型和参数类型。我很高兴你没有投反对票,因为我仍然认为这是一个很好的选择