2010-12-15 44 views
3

在我知道的C++和大多數面向對象的語言中,當從現有類A派生類B時,可以添加新方法,覆蓋現有方法並添加新數據成員。如果A在B中有一些你不想要的東西,那麼你不能消除它們。也許大多數情況下,這無關緊要,但我曾經有些時候希望我能做到。是否有OO語言允許從課程中減去功能?

是否有任何語言確實允許派生類被定義爲其父元素的某些元素被刪除?

回答

5

我想也許正確的方法來做這個子類應該提供一個空方法,覆蓋父的實現。

問題是子類與它們的超類有IS-A關係。如果子類取消了方法,在語義上它會是超類的一個實例嗎?多態性如何工作?當你將一個子類傳遞給一個期望超類類型的方法時,你會遇到各種各樣的痛苦,你應該能夠做到這一點。

這就是說,使用動態語言,您可以通過元編程在運行時刪除所需的方法。但是我只是做一個空方法,如果有意義的話可能會拋出一些UnsupportedOperation錯誤。

+2

override-and-throw模式廣泛用於.NET框架類庫中。例如,'ReadOnlyCollection '將爲所有由IList 接口契約規定的變異方法拋出'NotSupportedException'。除此之外,沒有任何事情可以合理地完成。 – cdhowie 2010-12-15 16:12:34

+0

Java在java.util中與它的集合做同樣的事情。請參見java.lang.UnsupportedOperationException。 – orangepips 2010-12-15 19:47:42

+0

@orangepips是正確的 - 但問題是一般的OO,而不是Java特定的。所以我只是採取了一點,通過它我的答案,但它使一般;) – hvgotcodes 2010-12-15 19:55:50

0

那麼......如果你遵循「面向方面編程」技術並使用接口,那麼你應該能夠有效地「隱藏」你不希望用戶看到的實現細節,因爲他們只能訪問到接口的成員

3

如果需要從父類(或父對象,它也適用於原型OO)中刪除功能,它不應該繼承首先。見Liskov substitution principle

設q(x)爲可證明的關於對象的屬性類型T.則Q(Y)的X應爲S型的對象ý真其中S是T.

的子類型

或者,去了 「是」:如果從BD繼承,那麼每DB。如果它沒有其方法之一,則不能是B

而且,實際的問題:這基本上使亞型多態性(能夠通過一個D每當需要一個A /預期),面向對象的非常基本的功能,是不可能的(因爲你無法知道是否亞型也暴露某種方法/財產)。

+0

假設B是基本的,D是派生的,那麼你是不是應該說:「如果D從B繼承,那麼每個D都是B.如果沒有它的方法之一,它就不能成爲B. 「 – JeremyP 2010-12-15 17:00:25

+0

@JeremyP:是的,謝謝。 – delnan 2010-12-15 17:10:55

+0

LSP很重要,但我繼承的tanglewad OO應用程序似乎將新類定義爲像某些現有類,但是有了這個和這個,沒有這個和其他的東西。類之間的差異被定義爲用另一個類來定義一個類,而不是一個適當的繼承關係,而不是替代的意圖。奇怪,醜陋,但這是我們正在努力。 – DarenW 2011-09-29 05:20:18

1

有些情況下,你可以得到一些東西類似這個。

例如,在Windows窗體,所有控件的屬性顯示在屬性網格,這樣你就可以在可視化設計器編輯它們的值。 Control基類暴露了一堆共同屬性,如文本,這並不適用於所有控件的,但(在Windows的視圖窗體隊)是一般不夠,你應該能夠把它們放在一個沒有控制不必知道它是否是一個按鈕,標籤,窗口等

雖然你不能真正在子類中刪除這些屬性 - 代碼仍然可以讀取和寫他們,如果你真的想 - 你可以將它們標記具有屬性來告訴工具隱藏它們,所以至少它們不是你的方式。

// Don't show this property in the Property Grid 
[Browsable(false)] 

// Don't save this property's design-time value to be reloaded at runtime 
// (i.e. don't generate a property assignment in the .designer.cs file) 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 

// Don't show this property in the editor's Intellisense code-completion lists 
[EditorBrowsable(EditorBrowsableState.Never)] 

public override string Text { 
    get { return base.Text; } 
    set { base.Text = value; } 
} 

當然,我們可以認爲,這只是因爲一個糟糕的設計,他們必須在所有創建這些屬性 - 這樣的設計顯然違反了Liskov Substitution Principle。 (他們可以爲每個這些共同屬性創建一個接口,這將允許後代選擇支持它們,同時讓代碼訪問它們而不向下轉換爲特定控件類型。)

1

使用面向方面編程幾乎可以做一些類似於你說的話。有很多針對此的語言,例如AspectJ。 無論如何,我想你應該考慮一個事實,那就是你可能設計了一個糟糕的體系結構,因爲做這種事情可能會降低軟件的可伸縮性(類並不總是提供連貫的服務)的質量。 面向對象編程是另一個研究領域,旨在完成您的建議。

相關問題