簡體   English   中英

有沒有辦法保證接口擴展Java中的類?

[英]Is there a way to guarantee an interface extends a class in 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

這是一個奇怪的要求,但你可以使用泛型完成某些事情:

<T extends MyInterface & MyAbstractClass>

這個問題表明你還沒有掌握interfaceclass的本質。 暫時忘記具體的Java語法,首先需要了解的是:接口是一組協議,應該是與實現無關的。 讓接口擴展一個類(面向實現)是沒有意義的。

回到你的具體問題,如果你想保證Flier總是一種Vehicle ,只需將后者改為interface ,讓前者擴展它(從其他協議擴展一個協議是有意義的)。 之后,您可以創建任何實現VehicleFlier類(抽象或具體)。

如果您對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>指定的內容必須同時擴展Vehicle並實現Car 通過添加self()您向程序員說明T對象應該是對象本身,因此如果他想要符合規范,則強制通配符實例匹配該類。

在Java 8中,您甚至可以為self方法定義默認實現。

我也希望有更好的方法來處理這樣的事情。

  1. 定義一個新包
  2. 創建一個新的接口(即HiddenOne),其范圍為“default”,方法為“implementMe(HiddenOne)”
  3. 將Vehicle and Flier移動到新包。
  4. 從HiddenOne繼承車輛和飛行器
  5. 在Vehicle中實現方法implementMe。

現在:無論何時你想從“Flier”實施,你必須從車輛延伸 (因為只有Vehicle可以實現implementMe )。

這很棘手,但效果很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM