![](/img/trans.png)
[英]How can I guarantee that a class that implements an interface also extends a class?
[英]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>
這個問題表明你還沒有掌握interface
和class
的本質。 暫時忘記具體的Java語法,首先需要了解的是:接口是一組協議,應該是與實現無關的。 讓接口擴展一個類(面向實現)是沒有意義的。
回到你的具體問題,如果你想保證Flier
總是一種Vehicle
,只需將后者改為interface
,讓前者擴展它(從其他協議擴展一個協議是有意義的)。 之后,您可以創建任何實現Vehicle
或Flier
類(抽象或具體)。
如果您對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方法定義默認實現。
我也希望有更好的方法來處理這樣的事情。
現在:無論何時你想從“Flier”實施,你必須從車輛延伸! (因為只有Vehicle可以實現implementMe )。
這很棘手,但效果很好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.