32

假设我有以下情况:

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

6 回答 6

32

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

处理这个问题的正确方法是把接口和实现完全分开,Vehicle也变成接口。Caretc可以扩展接口,Vehicle强制程序员实现相应的方法。如果您想在所有Vehicle实例之间共享代码,那么您可以使用(可能是抽象的)类作为任何需要实现该接口的类的父类。

于 2013-01-01T09:05:20.797 回答
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.

于 2013-01-01T09:09:52.340 回答
4

如果您可以控制Vehicle类,只需提取Vehicle为接口,然后提供基本实现。

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

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

<T extends Vehicle & Car>

但是除非您执行以下操作,否则您不能真正将其直接应用于 Car:

public interface Car<T extends Vehicle & Car>() {
    T self();
}

这很奇怪,并且不强制 self 方法实际返回 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对象应该是对象本身,因此如果他想符合规范,则强制通配符实例与类匹配。

in Java 8 you can even define a default implementation for the self method.

I also wish there was a better way to handle something like this.

于 2017-03-08T16:52:46.973 回答
2

这是一个奇怪的要求,但您可以使用泛型完成类似的事情:

<T extends MyInterface & MyAbstractClass>
于 2013-01-01T10:52:30.227 回答
1

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

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

于 2013-01-01T09:12:16.297 回答
0
  1. 定义一个新包
  2. 使用方法“implementMe(HiddenOne)”创建一个范围为“default”的新接口(即 HiddenOne)
  3. 将车辆和传单移动到新包裹。
  4. 从 HiddenOne 继承载具和飞行器
  5. 在 Vehicle 中实现方法 implementMe。

现在:每当您想从“Flier”实现时,您必须从 Vehicle 扩展 (因为只有 Vehicle 可以实现implementMe)。

这很棘手,但效果很好。

于 2013-01-02T14:07:47.073 回答