繼承
4.1 繼承的類型
4.1.1 實現繼承和接口繼承
在面向對象的編程中,有兩種截然不同的繼承類型:實現繼承和接口繼承
(1) 實現繼承:表示一個繼承派生於一個基類型,擁有該基類型的所有成員和函數。
(2) 接口繼承:表示一個類型只繼承了函數的簽名,沒有繼承任何實現代碼。
4.1.2多重繼承
一個c#類(除了Object類之外)都有一個基類,還可以有任意多個基接口。
4.1.3結構和類
結構不支持繼承,但支持接口繼承。定義結構和類可以總結為:
(1) 結構總是派生於System.ValueType,它們還可以派生於任意多個接口。
(2) 類總是派生於用戶選擇的另一個類,它們還可以派生於任意多個接口。
4.2 實現繼承
4.2.1 虛方法
把一個基類函數聲明為virtual,該函數就可以在派生類中重寫了。也可以把屬性聲明為virtual。
C#要求在派生類的函數重寫另一個函數時,要使用override關鍵字顯示聲明。
4.2.2 隱藏方法
如果簽名相同的方法在基類和派生類都進行了聲明,但該方法沒有聲明為virtual和override,派生類就會隱藏基類方法。
在大多數情況下,是要重寫方法,而不是隱藏方法,因為隱藏方法會存在為給定類的實例調用錯誤方法的危險。
在c#中,應使用new關鍵字聲明我們要隱藏一個方法(隱藏基類具有相同函數名和簽名的方法)
4.2.3 調用函數的基類版本
C#有一種特殊的語法用於從派生類中調用方法的基類版本:base.<MethodName>()(在java中用super關鍵字實現)。
注意,可以使用base.<MethodName>()語法調用基類中的任何方法,不必在同一個方法中的重載中調用它。
4.2.4 抽象類和抽象函數
C#運行把類和函數聲明為abstract,抽象類不能實例化,而抽象函數沒有執行代碼,必須在非抽象的派生類中重寫。如果類包含抽象函數,則該類必須是抽象類。
4.2.5 密封和密封方法
C#允許把類和方法聲明為sealed。對於類來說表示不能繼承該類,對於方法來說,表示不能重寫該方法。(java中對應sealed的關鍵字子final)
如果定義了一個新方法,但不想讓別人重寫它,首先不要把它聲明為virtual。如果要重寫某個基類方法,在派生類的重寫方法使用sealed關鍵字確保該方法提供的代碼為最終代碼,其他人不能再重寫它。
4.2.6 派生類的構造函數
構造函數的調用順序是先調用System.Object,再按照層級結構由上而下進行,直到到達編譯器要實例化的類為止。
4.3 修飾符
4.3.1 可見性修飾符
Public、proteced、internal、private、proteced internal
不要把類型定義為protected、private和protected intenal 因為這些修飾符對於包含在命名空間中的類型是沒有意義的。因此這些修飾符只能應用於成員。但是,可以用這些修飾符定義嵌套的類型(即包含在其它類型中的類型),因為在這種情況下,內嵌的類型也有成員狀態。如下:
Public class OuterClass
{
Protected class InnerClass
{
}
}
4.3.2 其它修飾符
下面的修飾符可以用於類型的成員,而且有不同的用途,在應用於類型時,其中的幾個修飾符也是有意義的。如abstract和sealed
new 應用於函數成員 成員用相同的簽名隱藏繼承的成員。
static 應用於所有成員 成員不在類的具體實例上執行。
virtual 僅類和函數成員可用 成員可以由派生類重寫
abstract 僅函數成員可用 虛擬成員定義了成員的簽名,但沒有提供實現的代碼
override 僅函數成員可用 成員重寫了繼承的虛擬或抽象成員
sealed 應用於類 成員重寫了繼承的虛擬成員,但繼承該類的任何類都不能重寫該成員。該修飾符必須和override一起使用。
extern 僅靜態方法 成員在外部用另外一種語言實現
4.4 接口
一般情況下,接口只能包含方法、屬性、索引器和事件的聲明。
在接口定義中還不允許聲明成員上的修飾符。接口成員總是公共的,不能聲明為虛擬或靜態。
4.4.1 定義和實現接口
4.4.2 派生的接口