[英]Creating many object types/classes just to use instanceof
我想知道我是否正在創建/分解對象類型為無意義的類,以及是否有更好的方法來做到這一點。
假設我有以下類( - > 擴展更高級的類):
Vehicle class - takes care of movement and a default speed
-->Car class - adds passengers
-->-->ElectricCar class - a default constructor
-->-->GasolineCar class - a default constructor
-->-->HybridCar class - a default constructor
-->Motorcycle class - a default constructor
-->Bike class - a default constructor, overrides speed
-->Segway class - a default constructor, overrides speed
如您所見,它們大多是默認構造函數。 所以我只是創建它們以防我需要使用instanceof條件語句。 我的大多數代碼最終都在Vehicle類中,因為我試圖避免在每個類中重復相同的代碼。 另外,我應該讓汽車抽象 ,對嗎? 我從不創建一個Vehicle對象。
這樣可以或有更好的方法嗎?
首先,只要代碼起作用並解決手頭的任務,我就會說它是“正確”的(所以是的, 沒關系 )。 話雖這么說,有些人更喜歡使用接口而不是抽象類(因為你可以實現多個接口但只能直接從一個祖先擴展)。 此外,如果您使用的是Java 8+,則可以向接口添加default
方法。 其他選擇可能包括有一個Vehicle
類,但一個VehicleType
enum
為外地Vehicle
類。
只要你的課程有意義並且提供一個功能,就不會有“太多課程”這樣的事情。 然而,在我看來,有一種pointless abstraction
。
如果您100%確定您只使用這些類別來確定車輛類型(引自您的問題),
我曾經需要使用instanceof條件語句
然后可能讓子類有資格作為無意義的抽象。 只需使用枚舉來描述您的車輛類型並繼續前進。
但是,如果您預期或計划將子類用於不僅僅是類型,那么通過使用子類來完成它是完全正確的,並且事實上在您的Vehicle類中有很多if / else或switch語句。
正如評論和答案中已經指出的那樣:這完全取決於你在那里建模的內容 。
但首先,關於你提到的意圖:
所以我只是創建它們以防我需要使用instanceof條件語句。
小心一點。 您應該避免根據對象的類型對對象的不同行為進行建模。 這里,類型信息是否是無關緊要的
instanceof
檢查隱式提供 boolean isMotorCycle()
類的方法,如注釋中所建議的那樣 enum Type { ... }
和switch
類型。 它們都遇到同樣的問題:當您向層次結構中添加新的類/類型時,您必須采用並更新查詢此類型信息的所有位置。 這可能成為維持噩夢。
類型檢查有合法用途。 但是當你最終編寫經常進行此類檢查的代碼時
void recharge(Vehicle v) {
if (v instanceof ElectricCar) ((ElectricCar)v).attachPlug();
if (v instanceof GasolineCar) ((GasolineCar)v).fillFuel();
if (v instanceof Bike) ((Bike)v).getDriver().takeRest();
...
}
然后,這表明您的層次結構存在問題。 可能是基類Vehicle
還不夠強大。 在上面的例子中,可以考慮將recharge()
方法拉入Vehicle
類,並簡單地調用它,依賴於多態實現。
在最壞的情況下,也可能是您嘗試建模的概念太過無關,無法在單個層次結構中組合。
您提到要對這些對象進行碰撞檢測。 這聽起來像你已經接近這樣的解決方案:
class Bike extends Vehicle {
@Override
void collideWith(Vehicle other) {
if (other instanceof Car) collideWithCar((Car)other);
if (other instanceof Segway) collideWithSegway((Segway)other);
...
}
}
有更優雅的解決方案。 您可能想了解與Double Dispatch相關的問題,也許可以查看策略模式 。
更一般地說,關於你是否有“太多課程”的問題,拇指有一些一般規則。
其中之一是接口分段原則 ,聲明你應該創建serval客戶端特定的insterfaces,而不是一個大的接口,它完成所有事情,因此結合了其他不相關的方法。 所以你沒有“太多的課程”,只要每個課程都有用。 你可以問自己:
GasolineCar
和ElectricCar
? 如果您需要區分ElectricCars,GasolineCars等,這一切都歸結為問題。如果沒有,您可以將所有內容放入車輛或汽車並創建車輛/汽車對象。
如果它不打算創建Vehicle對象,那么是的,它應該被標記為abstract。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.