[英]Whether to model a car object (and its parts such as engine) with has-a (composition) or is-a (inheritance)?
我正在開發一個包含Car對象的類庫。
困境是,汽車本身將是一個類別,如注冊號碼和汽車的其他一般信息。
但是汽車有發動機,底盤等。這些物體也需要建模。 它們應該是嵌入汽車的課程嗎? 如果沒有,嵌入式類的使用場景是什么?
我已經知道組合是“的一部分”,所以你可以模擬單獨的類並使用引擎類型,例如,在汽車的現場級別來實現這一點。 然而,“聚合”,其與在ctor中傳遞的類型“具有”關系,也適用(汽車“具有”引擎)。
我該走哪條路?
編輯:我目前正在做作業因此缺乏回復。 該類庫適用於基於汽車的Web應用程序。 我是一名專業的開發人員(我以.NET開發為生,但作為一名大三學生)所以這不是一個功課問題。
謝謝
這真的取決於你的應用程序。
例如,您可以將輪子實現為單獨的類,包含有關輪胎在哪個輪胎上的信息,磨損程度等等,但如果您的應用程序甚至不關心輪子,則整個課程都是浪費代碼。
我可以看到三個組合用例:
總結:使用組合作為封裝復雜性或消除重復的工具。 如果它不能用於其中一個目的,那么可能不值得為它做一個新課程。
一個類應該盡可能少地承擔責任,並將其他功能封裝並委托給其他類。 許多做一件事的小而簡單的類是可讀,穩定的代碼庫的標志。
是的,一輛汽車將“擁有”一個引擎,但我建議使用一個接口,類似的“有”關系。 再次,取決於教授,你可能會獲得獎勵積分讓工廠創建不同的汽車(適當,不?):
public class Car
{
private Engine engine;
public Car(Engine engine)
{
this.engine = engine;
}
public void accelerate()
{
this.engine.goFaster();
}
public void decelerate()
{
this.engine.goSlower();
}
}
public interface Engine
{
public void goFaster();
public void goSlower();
}
public class ReallyFastEngine implements Engine
{
public void goFaster()
{
// some code that goes really fast
}
public void goSlower()
{
// some code that goes slower
}
}
public class NotAsFastEngine implements Engine
{
public void goFaster()
{
// some code that goes not as fast
}
public void goSlower()
{
// some code that goes slower
}
}
public class CarFactory()
{
public static Car createFastCar()
{
return new Car(new ReallyFastEngine());
}
public static Car createNotAsFastCar()
{
return new Car(new NotAsFastEngine());
}
}
看作是家庭作業,並且根據您的導師/教授/老師的傾向,您可能最好沿着為引擎,車輪等編寫單獨的課程的路線。 即使它可能完全過度設計,並且您的應用程序可能不關心它們,但您的作業可能會標記為以下標准:
“他們確定了發動機艙”
“它有像Start()這樣的合理方法”
“將它們標記為將所有內容集中在一個實際上更簡單的大類中,因為它們顯然不理解組合”
或者其他什么,而不是這個線程中更務實的人適用於他們自己的設計的那種標准。
只將汽車模型分解為可以作為汽車范圍之外的單獨實體暴露的碎片。 考慮它的另一種方法是,當你轉動鑰匙時,你真的了解你的汽車是如何開始的嗎? 就典型的駕駛員而言,引擎蓋下的一切都是一個大而且嘈雜的黑匣子。 汽車工程師知道汽車所有者需要維護的常見零件,並明確地設計它們以用於不同級別的用戶交互,例如油尺或冷卻液儲液器補充蓋。
你能模仿汽車的每一塊嗎? 當然。 對各個火花塞進行建模是否有幫助? 可能不是。
您是否需要具有不同屬性(如顏色或尺寸)的汽車? 您是否需要具有乘客或牽引能力等不同能力的汽車? 一個不同的地方是你需要不同行為的汽車。 這是你真正需要考慮對具有屬性的Driver對象進行建模的地方,從簡單的反應時間到復雜的反應時間。
將車輛建模為面向對象或繼承的示例是有問題的,因為這些示例並未真正解釋定義類的基本屬性之間的真正區別。 這對StackOverflow來說並不陌生,但這個問題也不重復, 請參閱此SO線程 。 我和我的一個朋友進行了同樣的討論,並在我的博客上發布了一個日志 。 閱讀FAA認可的不同飛機類型以及每種類型的規定如何細分。 有許多不同類型的飛機,最大的分離是動力和無動力之間。
飛機是指用於或打算用於在空中飛行的裝置。
飛機是指比空氣重的發動機驅動的固定翼飛機,通過空氣對其機翼的動態反應在飛行中支撐。
飛艇是指可以轉向的發動機驅動的輕於空氣的飛機。
還有比空氣輕且比空氣重的空氣。 熱氣球無動力且比空氣輕。 飛艇是動力的,比空氣輕。 滑翔機無動力且比空氣重。 波音757的動力比空氣重,但增加了另一類“固定翼”,這與直升機不同,直升機也是動力的,比空氣重,但是是“旋轉翼”。
這是表格形式的前四個:
| Powered | Unpowered
---------------------------------------------------
Lighter-than-air | Blimp | Hot-air balloon
Heavier-than-air | 737 | Glider
你得到了照片。
你不能只說你將發動機與汽車分開建模,因為沒有發動機的汽車可能是一個完全不同的動物。 沒有發動機的汽車就像拖車一樣,也沒有發動機,但也沒有發動機。 在這些情況下,'is-a'和'has-a'都不適合我們構建對象的具體方式。 你沒有宣稱飛艇是一架“比空氣更輕”的飛機,所以它是一個熱氣球。 除了他們利用的物理學之外,它們都比空氣更輕的事實並沒有使它們以任何方式相關。 區別很重要,因為適用的規則和規定是不同的。 從另一個角度來看,我們並沒有將飛艇描述為具有“發動機”的熱氣球。 飛機沒有物理關系,這種關系是應該如何處理的。
如果您不需要將對象定義到該詳細程度,則可能不需要將它們建模到該詳細級別。
汽車將是一個頂級的對象。 包括數字,ID或描述等簡單字段。 並且會有像Engine這樣的復雜字段,它本身就是一個對象。
所以汽車看起來像:
class Car{
String ID;
Engine engine;
}
這是一種關系。
您可以決定引擎,Chasis等類的一個標准。
需要作為內部類(嵌入類)存在是否是實例
這些類可以在您的應用程序的其他地方使用。 在這種情況下
決策很簡單,就是讓這些類分開存在
(不是內部類)。
即使這些類沒有在你的應用程序中的其他地方使用,
標准可以是可測試性。 將這些類嵌入到內部和您的
設計是否可以進行單元測試,可以適當地測試你的
代碼提供良好的覆蓋范圍。
例如,如果你已經創建了一個引用一個的實例變量
引擎對象和此變量正在Car.And的構造函數中初始化
您的Engine類有一些需要測試的方法。 那怎么可能呢
你添加單元測試來檢查Engine類中的代碼? 可能你會的
在Car類中有一些暴露行為或Engine類允許的方法
你要編寫單元測試。 那么問題是是否需要揭露
Engine類的行為不會比Engine類更好
它自己站着?
或者,可能不需要明確地測試方法
Car中的方法的引擎類和單元測試引擎類代碼
同樣。 然后它反映了Engine類與Car類的緊密集成
並且意味着它可以保持為內在階級。
這取決於你想要做什么。 試圖在不知道用例的情況下設計一個“汽車”類(或任何其他類)是徒勞的。
您將根據您嘗試啟用的用例,以非常不同的方式設計類及其關系和交互。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.