我有這些課程:
enum Brand {
FORD, FERRARI, TESLA, RENAULT;
}
public class Car {
Brand brand;
String plate;
...
}
//getters and setters
想象一下,出于某種原因,我需要讓 Car 成為兩個新類的超類:CombustionCar 和 ElectricCar。新要求之一是 ElectricCar 的品牌屬性必須始終是 TESLA 值,而不是任何其他值。我想了一些解決方案:
- 我可以在 superclass Car 上保留 Brand attr,并讓 ElectricCar 建構式設定 TESLA 品牌。但是這種方式可以讓我在創建物件后設定一個新品牌
public class ElectricCar extends Car {
public ElectricCar(...){
super(Brand.TESLA, ...);
}
ElectricCar ec = new ElectricCar(...);
ec.setBrand(Brand.FORD);
- 我可以從超類中取出 Brand attr 并將其設定在兩個子類上,但在 ElectricCar 中將其設定為帶有 final 的類屬性,因此任何人都可以設定新值
public class ElectricCar extends Car {
public static final Brand brand = Brand.TESLA;
...
}
public class CombustionCar extends Car {
private Brand brand;
...
}
- 避免繼承和使用組合,但這樣我將無法使用,例如,包含兩者的串列:
public class ElectricCar {
private Car car;
private Brand brand = Brand.TESLA;//with no setter
...
}
public class CombustionCar {
private Car car;
private Brand brand;
...
}
我要求最優雅和最穩定的解決方案,我認為他們中的任何一個都可以很好地解決我的問題。
uj5u.com熱心網友回復:
鑒于您需要一個不可編輯的電動汽車品牌,您的第一個解決方案是不正確的。
您的第二個解決方案根本不起作用,除非您同時覆寫品牌欄位的 getter 和 setter 以使用靜態欄位,這不是“優雅且易于維護”
您的第三個解決方案沒有使用面向物件的概念。
我將使用的一個簡單解決方案是在 Car 超類中使用欄位品牌及其 getter,但我只會在 CombustionCar 類中定義 setter。或者,如果您擴展您的模型,您可以創建一個實作 setter 的中間抽象超類“FreeBrandCar”。
CombustionCar 中的 setter 解決方案
abstract public class Car {
protected String brand;
protected Car(final String b) {
this.brand = b;
}
public String getBrand() {
return this.brand;
}
}
public class ElectricCar extends Car {
public ElectricCar() {
super("Tesla");
}
}
public class CombustionCar extends Car {
public CombustionCar(final String b) {
super(b);
}
public void setBrand(final String b) {
this.brand = b;
}
}
具有中間類的解決方案
abstract public class Car {
protected String brand;
protected Car(final String b) {
this.brand = b;
}
public String getBrand() {
return this.brand;
}
}
abstract public class FreeBrandCar extends Car {
public FreeBrandCar (final String b) {
super(b);
}
public void setBrand(final String b) {
this.brand = b;
}
}
public class ElectricCar extends Car {
public ElectricCar() {
super("Tesla");
}
}
public class CombustionCar extends FreeBrandCar {
public CombustionCar(final String b) {
super(b);
}
}
它尊重您的要求:
public void test() {
ElectricCar ec = new ElectricCar();
ec.setBrand("..."): // Doesn't compile
CombustionCar cc = new CombustionCar("Ford"); // OK
cc.setBrand("Fiat"); // OK
Arrays.asList(ec, cc)
.stream()
.forEach(car -> System.out.println(car.getBrand())); // prints Tesla and Fiat
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/348620.html
下一篇:在宣告性管道中并行運行
