有没有办法保证接口扩展Java中的类?

假设我有以下情况:

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() { ... } } 

Java接口不能扩展类,这是有道理的,因为类包含无法在接口中指定的实现细节。

解决此问题的正确方法是通过将Vehicle转换为接口来完全将接口与实现分开。 Car等可以扩展Vehicle界面,迫使程序员实现相应的方法。 如果要在所有Vehicle实例之间共享代码,则可以使用(可能是抽象的)类作为需要实现该接口的任何类的父类。

您可以重新排列类和接口,如下所示:

 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

这是一个奇怪的要求,但你可以使用generics完成某些事情:

  

这个问题表明你还没有掌握interfaceclass的本质。 暂时忘记具体的Java语法,首先需要了解的是:接口是一组协议,应该是与实现无关的。 让接口扩展一个类(面向实现)是没有意义的。

回到你的具体问题,如果你想保证Flier总是一种Vehicle ,只需将后者改为一个interface ,让前者扩展它(从另一个协议扩展一个协议是有意义的)。 之后,您可以创建任何实现VehicleFlier类(抽象或具体)。

如果您对Vehicle类具有控制权,则只需将Vehicle作为接口提取,然后提供基本实现。

如果您无法控制Vehicle类,例如因为它是您正在使用的框架或第三方库的一部分,则无法使用Java。

您可以做的最接近的事情是使用Generics多个通配符表示法。

  

但你不能直接将它直接应用于Car,除非你做这样的事情:

 public interface Car() { T self(); } 

这是机器人很奇怪,并没有强制自我方法来实际返回自我,这只是一个强烈的提示/建议。

你会像这样实现一辆Car

 public class CitroenC3 extends Vehicle implements Car { @Override public CitroenC3 self() { return this; } } 

一个人可以像这样使用Car

 Car car = obtainCarInSomeWay(); Vehicle v = car.self(); Car c = car.self(); 

它们应该都是有效的语法。

编译器在此强制执行的是您在Car指定的内容必须同时扩展Vehicle并实现Car 。 通过添加self()您向程序员说, T对象应该是对象本身,因此如果他想要符合规范,则强制通配符实例匹配该类。

在Java 8中,您甚至可以为self方法定义默认实现。

我也希望有更好的方法来处理这样的事情。

  1. 定义一个新包
  2. 创建一个新的接口(即HiddenOne),其范围为“default”,方法为“implementMe(HiddenOne)”
  3. 将Vehicle and Flier移动到新包。
  4. 从HiddenOneinheritance车辆和飞行器
  5. 在Vehicle中实现方法implementMe。

现在:无论何时你想从“Flier”实施,你必须从车辆延伸 (因为只有Vehicle可以实现implementMe )。

这很棘手,但效果很好。