一。何時使用抽象類別
當需要一組相關組件來包含一組具有相同功能的方法,但同時要求在其他方法實現中具有靈活性時,可以使用抽象類別。當預料可能出現版本問題時,抽象類別也具有價值,因為基類比較靈活並易於被修改。有關詳細資料,請參見抽象類別與介面建議。
抽象類別與介面建議請參見
抽象類別 | 組件中的多態性 | MustInherit (Visual Basic) | abstract (C#)
選 擇將功能設計為介面還是抽象類別(在 Visual Basic 中為 MustInherit 類)有時是一件困難的事。“抽象類別”是一種不能執行個體化而必須從中繼承的類。抽象類別可以完全實現,但更常見的是部分實現或者根本不實現,從而封裝繼承類的通 用功能。有關詳細資料,請參見抽象類別。
相反,“介面”是完全抽象的成員集合,可以被看作是為操作定義合約。介面的實現完全留給開發人員去做。
介面和抽象類別對組件互動都很有用。如果一個方法要求一個參數形式的介面,則任何實現該介面的對象都可以用在該參數中。例如:
' Visual Basic
Public Sub Spin (ByVal widget As IWidget)
End Sub
// C#
public void Spin (IWidget widget)
{}
此方法可以接受任何將 IWidget 實現為小組件參數的對象,即使 IWidget 的實現可能相差很大。抽象類別也允許這種多態性,但須注意以下幾點:
類可能只是從一個基類繼承,所以如果要使用抽象類別為一組類提供多態性,這些類必須都是從那個類繼承的。
抽象類別還可能提供已實現的成員。因此,可以用抽象類別確保特定數量的相同功能,但不能用介面這樣做。
這裡是一些建議,協助您決定使用介面還是抽象類別為組件提供多態性。
如果預計要建立組件的多個版本,則建立抽象類別。抽象類別提供簡單易行的方法來控制組件版本。通過更新基類,所有繼承類都隨更改自動更新。另一方面,介面一旦建立就不能更改。如果需要介面的新版本,必須建立一個全新的介面。
如果建立的功能將在大範圍的全異對象間使用,則使用介面。抽象類別應主要用於關係密切的對象,而介面最適合為不相關的類提供通用功能。
如果要設計小而簡練的功能塊,則使用介面。如果要設計大的功能單元,則使用抽象類別。
如果要在組件的所有實現間提供通用的已實現功能,則使用抽象類別。抽象類別允許部分實作類別,而介面不包含任何成員的實現。
------------------------------------------------------------------------------------------
二。網友的疑問
using System;
abstract public class Window
{
protected int top;
protected int left;
public Window(int top1,int left1)
{
this.top = top1;
this.left = left1;
}
abstract public void DrawWindow();
}
public class ListBox:Window
{
protected string listContents;
public ListBox(int top1,int left1,string contents):base(top1,left1)
{
this.listContents = contents;
}
public override void DrawWindow()
{
Console.WriteLine(listContents);
}
}
public class Tester
{
static void Main()
{
Window[] win = new Window[2];
win[0] = new ListBox(1,2,"Fitst");
win[1] = new ListBox(3,4,"Second");
for(int i=0;i<2;i++)
{
win.DrawWindow();
}
Console.Read();
}
}
說是不能執行個體化,Window[] win = new Window[2];這個不算是執行個體嗎?
------------------------------------------------------------------------------------------
三。對此釋疑
幸好請教了一位耐心的老大。
Window[] win = new Window[2]
這句真正執行個體化的是數組對象,而是Window抽象類別型。
你又在其後這樣寫:
win[0] = new ListBox(1,2,"Fitst");
win[1] = new ListBox(3,4,"Second");
其實還是把衍生類別的執行個體化放到數組元素裡了。
如果你把上邊new ListBox的兩句注掉,改成一句win[0] = new Window(0,0)放進去,再試試
這時就編譯不過了,並且會給你明確的提示。
------------------------------------------------------------------------------------------
四。系統總結一下MS關於抽象類別的說法
任何情況下,抽象類別都不應進行執行個體化,因此,正確定義其建構函式就非常重要。確保抽象類別功能的正確性和擴充性也很重要。下列準則有助於確保抽象類別能夠正確地設計並在實現後可以按預期方式工作。
不要在抽象類別型中定義公用的或受保護的內部(在 Visual Basic 中為 Protected Friend)建構函式。
具有 public 或 protected internal 可見度的建構函式用於能進行執行個體化的類型。任何情況下抽象類別型都不能執行個體化。
應在抽象類別中定義一個受保護建構函式或內部建構函式。
如果在抽象類別中定義一個受保護建構函式,則在建立衍生類別的執行個體時,基類可執行初始化任務。內部建構函式可防止抽象類別被用作其他程式集中的類型的基類。
對於您提供的每個抽象類別,至少應提供一個具體的繼承類型。
這樣有助於庫設計者在設計抽象類別時找到問題所在。同時意味著開發人員在進行進階別開發時,即使不瞭解抽象類別和繼承,也可以使用具體類而不必學習這些概念。
抽象類別具有以下特性:
抽象類別不能執行個體化。
抽象類別可以包含抽象方法和抽象訪問器。
不能用 sealed(C# 參考)修飾符修改抽象類別,這意味著抽象類別不能被繼承。
從抽象類別派生的非抽象類別必須包括繼承的所有抽象方法和抽象訪問器的實實現。
在方法或屬性聲明中使用 abstract 修飾符以指示方法或屬性不包含實現。
抽象方法具有以下特性:
抽象方法是隱式的虛方法。
只允許在抽象類別中使用抽象方法聲明。
因為抽象方法聲明不提供實際的實現,所以沒有方法體;方法聲明只是以一個分號結束,並且在簽名後沒有大括弧 ({ })。例如:
實現由一個重寫方法提供,此重寫方法是非抽象類別的成員。
在抽象方法聲明中使用 static 或 virtual 修飾符是錯誤的。
除了在聲明和調用文法上不同外,抽象屬性的行為與抽象方法一樣。
在靜態屬性上使用 abstract 修飾符是錯誤的。
在衍生類別中,通過包括使用 override 修飾符的屬性聲明,可以重寫抽象的繼承屬性。
抽象類別必須為所有介面成員提供實現。
實現介面的抽象類別可以將介面方法映射到抽象方法上。
qltouming(緣木漁人)
2006-11-02