我正在處理我的項目中的類層次結構,基本上我有類似的情況,就像你在你的問題中描述的那樣。
比方說,我有基本類型的對象,它是我的工具包中所有其他類的絕對根。所以自然,一切都是直接或通過它的子類派生的。每個Object-derived類必須提供一個通用的功能,但在某些葉類中,效果與其他類中的效果稍有不同。例如,每個對象的大小和位置都可以通過屬性或方法來改變,比如Position = new Point(10,10),Width = 15等等。但是有些類應該忽略屬性的設置或者根據自己修改內在狀態。想想停靠在父窗口左側的控件。你可以設置所有你喜歡的Height屬性,但它通常會被忽略,因爲這個屬性真的取決於父容器控件的高度(或者它的ClientArea高度或者像這樣)。
因此,在您需要「自定義」行爲的地方,實現基本通用功能的Object抽象類就可以了。如果Object提供在Height屬性的setter中調用的受保護的虛擬SetHeight方法,則可以在您的DockedControl類中重寫該方法,並且僅在停靠爲無時才允許更改高度,而在其他情況下,您可以限制或完全忽略。
所以我們很高興,但現在我們需要對Click,Hover等鼠標事件作出反應的對象。所以我們從抽象的Object類派生MouseAwareObject並實現事件和東西。
現在客戶端需要可停靠鼠標的對象。所以我們從DockableObject派生出來......嗯,現在呢?如果我們可以做多重繼承,那麼我們可以做到,但是我們遇到了鑽石問題,而且重複的界面不明確,我們需要處理它。在新的類和代理外部調用中,我們可以使用兩個Dockable類和MouseAware類來提供功能。
最後想到的是製作IDockable和IMouseAware接口,並讓它們定義功能並將它們自由添加到需要傳遞具體行爲/實現的對象中。
我想我會拆分我的基類成部分,並留下我的對象具有非常有限的「核心」屬性和方法集和其餘的功能,實際上是對象的可選項作爲類型,但在具體情況下需要移動到像IResizable,IDockable,IMakeAWorldABetterPlaceAble等接口。通過這種解決方案,可以將行爲「附加」到Object派生類,而無需將Draggin虛擬或純虛擬(抽象)方法從根基類一直拖到葉類。
在所有受影響的類中實現接口當然是不方便的,但是您始終可以實現一些「適配器」並僅將呼叫轉發給它們。這樣你就沒有重複的實現(當然有一些延伸),並且在任務的實現(Resize可能意味着不同類的不同事物)和期望的客戶端代碼之間解耦。
也許這不是你的問題的理想答案,但也許它會暗示你自己的解決方案。
爲什麼之前的答案被刪除? –
這個問題是__not language agnostic__如果是的話,你可以考慮使用mixins這些更優雅的替代方法,它根據你描述的語言的本質(使用接口,我假設C#或java?)是根本不存在的 –
@Pablo Fernandez mixin是我認爲第一個解決方案的名字 –