簡體   English   中英

最好擴展一個類或直接修改它?

[英]Better to extend a class or modify it directly?

所以我正在為Java中的數據結構創建可視化。 我已經開始實現數據結構(二進制搜索樹),但我需要為包含的節點類添加一些額外的功能。 就約定和最佳實踐而言,我是否應該使用此附加功能創建節點的子類,還是應該修改我擁有的內容並將其記錄在那里?

我的問題類似於這里提出的問題但這有點過頭了。

我知道這對我正在做的事情並不重要,所以我更多地問這個問題。

編輯:我可能應該更清楚。 我的修改實際上並沒有改變原始實現,只是添加了幾個額外的字段(x和y coords以及一個布爾值來設置是否突出顯示該節點)以及訪問/修改這些字段的函數。 我正在使用的節點類也包含在BST實現中

從閱讀你的答案看起來似乎有兩個案例的論點。 我同意創建一個單獨的類或接口可能是最好的事情。 創建另一個類似乎可能會變得棘手,因為您仍然需要一種從節點中提取數據的方法。 我正在使用的BST實現是通用的,並且在Node類或BST類中沒有任何這樣的功能只返回數據,所以至少我必須添加它。

感謝您提供豐富的回復。

要回答的問題是,當您沒有可視化數據結構時,“基本功能”是否有用,甚至是可取的?

您可能根本不想擴展該類。 沒有更多細節,在我看來,你有一個有效的數據結構。 您可以創建一個知道如何對其進行虛擬化的新類。

也就是說,代替數據結構而不是知道如何自我可視化,您有一個數據結構,另一個知道如何可視化數據結構的類。 哎呀 - 您可能會發現它會演變成另一個完整的類層次結構,因為您可能需要可視化隊列,堆棧等等。無需使用二進制搜索樹。

既然你一般都在問,這里的答案簡短: 這實際上取決於具體情況

首先,假定子類與其父類具有“IS-A”關系。 如果你不能說你的新子類是一個特定類型的原始類,那你就是在問一個錯誤的問題,並且應該創建一個新的,無關的類。

  • 如果新代碼與類的核心目的密切相關,並且適用於類的所有成員(例如所有BST),則修改可能更好。 凝聚力是好的。
  • 如果您的新代碼與該類的核心目的相關,但僅與該類型的某些對象有關(例如,只有平衡的BST),則子類化可能是要走的路。
  • 根據您正在更改的內容,代碼的使用位置,使用它的人/組織的數量,等等,您的更改可能會導致其他代碼中出現意外行為,因此在修改現有代碼之前應該三思而后行。 這並不意味着自動對常用事物進行子類化; 由於上述原因,這通常是錯誤的。

在您的具體情況下,我同意n8wrl; 由於可視化與數據結構無關,因此實現一個完全獨立的Visualizable接口可能比制作DrawableBSTNode子類更好。

我想說,在向現有實現添加功能的一般情況下,您應該擴展現有實現而不是修改它。

這是我的推理。 如果除了二進制搜索樹實現之外的任何地方使用該節點,那么當您修改它時,您需要找到它用於確保這些位置都不與您的修改沖突的任何地方。 雖然只是以新方法的形式添加功能通常不會引起問題,但它可能會導致問題。 你永遠不知道如何使用一個對象。

其次,即使它僅用於二進制搜索樹,您仍然需要確保BST的實現與您的修改一致。

最后,如果你擴展它,你不必擔心第一點和第二點。 並且您可以獲得額外的好處,即您的修改始終與原始實施分開。 這樣可以更輕松地跟蹤您所做的事情並對其進行評論。

沒有簡單的答案,知道何時以及如何添加功能是您必須要學習的東西。

只是添加到基類似乎是簡單的解決方案,但它污染了您的基類。 如果這是一個類,你可以合理地期望使用另一個程序(甚至你的程序的一部分),你所添加的功能是否適合你班級的責任? 如果不是這可能是一個不好的舉動。 您是否添加了將基類鏈接到特定用途的依賴項? 因為如果你正在拋出代碼重用窗口。

繼承是許多工程師所傾向的解決方案,這是一條誘人的路線。 但是,隨着我成長為工程師,這是我謹慎使用的。 繼承應僅用於真正的is-a關系,並且您需要尊重行為子類型,否則您將在以后后悔。 而且由於Java只允許單繼承,這意味着你只能在子類型中獲得一次。

組合(尤其是界面)通常是一個更好的主意。 通常看起來像是一種關系的關系實際上是一種關系。 或者有時您真正需要的是一個輔助類,它有許多函數可以將原始類作為參數。

但是有了組合,有一個問題,想要在樹中存儲這些對象。 這里的解決方案是接口。 您不需要存儲節點的樹。 您希望對象具有可以為您提供節點的接口。

public interface HasNode {
    public Node getNode();
}

你的節點類是一個帶有getNode的HasNode,只是返回它。 您的NodeVisualizer類也是一個HasNode,現在您也可以在樹中存儲NodeVisualizers。 當然現在你有另一個問題,你的樹可能包含NodeVisualizers和Nodes,這不會很好。 另外,當您從樹函數中獲取HasNode時,您必須將它們轉換為正確的實例,這很難看。 你會想要使用模板,但這是另一個答案。

混合邏輯上獨立的功能將導致混亂。 子類化是一種非常特殊的關系,經常被過度使用。 子類化用於Is-a-Kind關系。

如果你想要想象一下,為什么不為它創建一個完全獨立的類呢? 您可以簡單地將Node對象傳遞給它。 (或者甚至更好,使用接口。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM