我的問題的一個例子如下所示。兩個類Car和Bike具有相同的欄位(wheel和bodyColor)。
在類中AssembleVehicle,該方法getDetails幾乎Car與 and重復Bike。有什么辦法可以去除冗余或提高編碼標準?
class Vehicle {
Car car;
Bike bike;
//setter & getter
}
class Car {
String wheel;
String bodyColor;
//setter & getter
}
class Bike {
String wheel;
String bodyColor;
//setter & getter
}
class AssembleVehicle {
public void init(Vehicle v) {
getDetails(v.getCar);
getDetails(v.getBike);
}
private void getDetails(Car c) {
String wheel = c.wheel;
String bodyColor = c.bodyColor;
}
private void getDetails(Bike c) {
String wheel = c.wheel;
String bodyColor = c.bodyColor;
}
}
在這里,我們如何去除getDetails? 的代碼冗余。我們可以只使用一次這種方法嗎?
我對泛型的理解是:泛型允許您將“泛型”方法或類自定義為您正在使用的任何型別。例如,假設您有一個將兩個數字相加的方法。為了使用型別本身,您可能必須創建此方法的多個版本。
uj5u.com熱心網友回復:
以這種方式考慮 OOP 放置了錯誤的重點。即使您解決了最初的問題,即在其中包含一輛汽車和一輛自行車的 Vehicle(認真的?),帶有wheel 和bodyColor 欄位的Vehicle 超類的“改進”模型可能已損壞(取決于您的實際域)正在作業)。例如自行車輪和汽車輪是非常不同的,而雪橇是沒有任何輪子的車輛。乍一看相似的東西并不總是進入超級課堂的好人選。
問題是我們傾向于假設,如果一個類別的兩個例子有一些共同的特征,那么這些特征對這個類別的所有成員都存在(順便說一句,這種概括的傾向也可能是社會中許多問題的原因) .
OOP 的威力并非來自提取像 Vehicle 這樣的超類并“重用”某些欄位。直接子類化是一種非常嚴厲的措施,不應輕易應用,因為這意味著所有現在和未來的子類都必須繼承超類的完整契約(資料和行為)。一旦你想添加一個新的子類并被迫做出例外,你就會知道模型是錯誤的。改變它會影響所有現有的子類。
一個更好的工具是提取介面,封裝一類類的某些方面:
interface Wheeled {
String getWheels();
}
class Car implements Wheeled {
private String wheels;
public String getWheels() {
return wheels;
}
}
class Bike implements Wheeled {
private String wheels;
public String getWheels() {
return wheels;
}
}
如果您只對車輪感興趣,這將允許對汽車和自行車進行相同的處理:
List<Wheeled> wheeledVehicles = new ArrayList<>();
wheeledVehicles.add(new Car());
wheeledVehicles.add(new Bike());
wheeledVehicles.get(0).getWheels());
如果您對車身顏色,甚至車輪和車身顏色感興趣,您可以使用以下界面:
interface Wheeled {
String getWheels();
}
interface Coloured{
String getBodyColour();
}
interface WheeledAndColoured extends Wheeled, Coloured {}
這使得:
List<WheeledAndColoured> wheeledAndColouredVehicles = new ArrayList<>();
wheeledAndColouredVehicles.add(new Car());
wheeledAndColouredVehicles.add(new Bike());
WheeledAndColoured first = wheeledAndColouredVehicles.get(0);
first.getWheels());
first.getBodyColour());
如果你真的想要,你可以將wheels欄位提取到一個超類中,但是直接的收益是有限的。私有欄位是一個實作細節,將它們拉入超類肯定不是那種會產生很大差異的重用型別。同時,它會在這些類之間創建非常強的依賴關系,并使未來的更改更加困難。
也許如果您需要實作一些與輪子相關的“復雜”邏輯,是時候創建 Wheels 類了:
class Wheels {
private String type;
private int number;
private double price; // don't use double for price in real code
public double getReplacementCosts() {
return ((double) number) * price;
}
}
現在 Car 類可以作為一個欄位與 Wheels 類協作:
class Car implements Wheeled {
private Wheels wheels;
public String getWheels() {
return wheels.getType();
}
public double getMaintenanceCosts() {
return wheels.getReplacementCosts();
}
}
請注意,因為我們沒有將 Car 和 Bike 與一個共同的超類聯系起來,所以我們不會被迫更改 Wheeled 介面或 Bike 類。如果您想將 Wheels 邏輯添加到 Bike,那么您可以輕松地這樣做,但您不是被迫的。如果輪子欄位在共享超類 Vehicle 中,您會是這樣。
所以座右銘是:支持協作而不是擴展,因為它更靈活。
uj5u.com熱心網友回復:
我同意其他評論者的意見,即 Vehicle 類實際上沒有意義。我建議聽從他們的建議,讓 Car 和 Bike 擴展 Vehicle 類。這比使用泛型要好,因為您可以“保證”不能將 AssembleVehicle 與不是車輛的類一起使用,并且不滿足具有輪子和 bodyColour 的要求。
但是,如果您仍然想使用泛型,可以使用以下方法:
class Car {
String wheel;
String bodyColor;
//setter & getter
}
class Bike {
String wheel;
String bodyColor;
//setter & getter
}
class AssembleVehicle <T> {
public void init(T vehicle) {
getDetails(vehicle);
}
private void getDetails(T vehicle) {
String wheel = vehicle.wheel;
String bodyColor = vehicle.bodyColor;
}
}
這允許您只撰寫一次 getDetails 方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/377918.html
上一篇:在Java泛型中指定Map
