假设我有以下情况:
public abstract class Vehicle {
public void turnOn() { ... }
}
public interface Flier {
public void fly();
}
有没有办法可以保证任何实现Flier
的类都必须扩展Vehicle
?我不想让Flier
成为一个抽象类,因为我希望能够以类似的方式混合其他一些接口。
例如:
// I also want to guarantee any class that implements Car must also implement Vehicle
public interface Car {
public void honk();
}
// I want the compiler to either give me an error saying
// MySpecialMachine must extend Vehicle, or implicitly make
// it a subclass of Vehicle. Either way, I want it to be
// impossible to implement Car or Flier without also being
// a subclass of Vehicle.
public class MySpecialMachine implements Car, Flier {
public void honk() { ... }
public void fly() { ... }
}
答案 0 :(得分:26)
Java接口不能扩展类,这是有道理的,因为类包含无法在接口中指定的实现细节。
处理此问题的正确方法是将Vehicle
转换为接口,从而将接口与实现完全分开。 Car
e.t.c.可以扩展Vehicle
接口以强制程序员实现相应的方法。如果要在所有Vehicle
实例之间共享代码,则可以使用(可能是抽象的)类作为需要实现该接口的任何类的父类。
答案 1 :(得分:9)
您可以重新排列类和接口:
public interface IVehicle {
public void turnOn();
}
public abstract class Vehicle implements IVehicle {
public void turnOn() { ... }
}
public interface Flier extends IVehicle {
public void fly();
}
这样,Flier
的所有实现都可以保证实现车辆的协议,即IVehicle
。
答案 2 :(得分:2)
这是一个奇怪的要求,但你可以使用泛型来完成某些事情:
<T extends MyInterface & MyAbstractClass>
答案 3 :(得分:1)
这个问题表明你没有掌握interface
和class
的本质。暂时忘记具体的Java语法,首先需要了解的是:接口是一组协议,应该是与实现无关的。让接口扩展一个类(面向实现)是没有意义的。
回到你的具体问题,如果你想保证Flier
始终是一种Vehicle
,只需将后者改为interface
并让前者扩展它(它将一个协议扩展到另一个协议是否有意义)。之后,您可以创建任何实现Vehicle
或Flier
的类(抽象或具体)。
答案 4 :(得分:1)
如果你对Vehicle
类有控制权,只需提取Vehicle
作为接口,然后提供基础实现。
如果您无法控制Vehicle
类,例如因为它是您正在使用的框架或第三方库的一部分,则无法用Java进行操作。
您可以做的最接近的事情是使用Generics多个通配符表示法。
<T extends Vehicle & Car>
但你不能直接将它直接应用于Car,除非你做这样的事情:
public interface Car<T extends Vehicle & Car>() {
T self();
}
哪种机器人很奇怪,并没有强制实施自我实现方法,这只是一个强烈的提示/建议。
您可以像这样实施Car
:
public class CitroenC3 extends Vehicle implements Car<CitroenC3> {
@Override
public CitroenC3 self() {
return this;
}
}
可以像这样使用Car<?>
:
Car<?> car = obtainCarInSomeWay();
Vehicle v = car.self();
Car c = car.self();
它们应该都是有效的语法。
编译器在此强制执行的是您在Car<WHICH>
中指定的内容,因为WHICH必须扩展Vehicle
并实现Car
。通过添加self()
,您要向程序员说明T
对象应该是对象本身,因此如果他希望符合规范,则强制通配符实例匹配该类。 / p>
在Java 8中,您甚至可以为self方法定义默认实现。
我也希望有更好的方法来处理这样的事情。
答案 5 :(得分:0)
现在:每当您想要从“Flier”实施时,您必须从Vehicle 延伸! (因为只有车辆可以实施 implementMe )。
这很棘手,但效果很好。