C#本質論6.0第六章:繼承
阿新 • • 發佈:2018-10-23
行為 實體 sta 密封類 類型 繼承鏈 tac 預測 兩個類
基類型與派生類型之間的轉型:
顯式轉型與隱式轉型:
從派生類型轉型為基類型稱為隱式轉型,轉型總會成功,不會引發異常。
從基類型轉型為派生類型稱為顯式轉型,在轉型過程中可能會失敗,為了執行顯示轉型,要在原始引用名稱之前,將要轉換成的類型放在前面圓括號中。
自定義轉換:
不相關的類型之間也能進行相互轉換,C#允許類型包含顯式與隱式轉型轉換符,在轉型有可能失敗時,開發者應定義顯式轉型操作符。
class GPSCoordinates { //... public static implicit operator UTMCoordinates( GPSCoordinates coordinates) { //implicit 隱式轉換關鍵字 //explicit 顯式轉換關鍵字 } }
單繼承:
一個類不能直接從兩個類派生。
在極少數需要多繼承結構的時候,一般的解決方案是使用聚合:
- 聚合:一個類包含另一個類的實例。
public class PdaItem { //主要基類 } public class Person { //字段類 } public class Contact : PdaItem { //派生類 //持有另一個類的實例 private Person InternalPerson{get; set;} public string FirstName { get{return InternalPerson.FirstName;} set{InternalPerson.FirstName = value;} } //... }
缺點:
1. 因委托而增加復雜性。
? 2. 在字段類上新增的任何方法都需要人工添加到派生類中,否則Contact無法公開新增的功能。
密封類:
為了正確設計類,讓其他人通過繼承來拓展它的功能,需要對它進行全面測試,驗證派生能成功的進行。為了避免非預期的派生,並避免出現因此而產生的問題,可以把類標記為sealed。
public sealed class CommandLineParser
{
//...不能從該類派生出其他類
}
基類的重寫:
在基類中,必須將允許重寫的每個成員標記為virtual,假如一個public或protected成員沒有包含virtual修飾符,就不允許子類重寫該成員。
public class PdaItem
{
public virtual string Name{get;set;}
}
public class Contact : PdaItem
{
public override string Name
{
//...
}
}
- 對成員進行重載,會造成運行時調用最深的或者說派生的最遠的實現。因此,虛方法不應包含關鍵代碼,如果派生類重寫了它,那麽那些代碼將永遠得不到調用。不要在構造器中調用會影響所構造對象的任何虛方法,假如這個虛方法在當前要實例化的類型的派生類型中進行了重寫,就會調用重寫的實現,但在繼承層次結構中,字段尚未完全初始化,所以調用虛方法將導致無法預測的行為。
- 如果沒有對虛方法進行重寫,編譯器會報告警告信息,我們可以通過new關鍵字來解決該問題:
- new修飾符在基類面前隱藏了派生類重新聲明的成員,這時不是調用派生的最遠的成員,相反,是搜索繼承鏈,找到使用new修飾符的那個成員之前的成員,然後調用該成員。如果繼承鏈中僅包含兩個類,就會使用基類的成員,感覺就像是派生類沒有重寫那個成員。
- 對類使用sealed修飾符可以禁止從該類繼承,虛成員也可以密封。一般很少將整個類標記為密封,除非是遇到迫切需要這種限制的情況。
- base成員:重寫成員時,調用該成員的基類版本。
- override修飾的任何成員都自動成為虛成員。
構造器:
在實例化一個派生類的時候,運行時首先調用基類的構造器,以避免繞過對基類的初始化。假如基類沒有可訪問的默認構造器,我們需要在派生類構造器的頭部顯式指定要運行哪一個基類構造器。
public class Contact : PdaItem
{
public Contact(string name):base(name)
{
Name = name;
}
}
抽象類:
(abstract)抽象類是僅供派生的類,無法實例化抽象類,只能實例化從它派生的類。抽象成員定義了從抽象實體派生的對象應包含什麽,但這種成員不包含實現。一個類要從抽象類成功的派生,必須為抽象基類的抽象方法提供具體的實現。
- 不可實例化只是抽象類的一個較次要的特征,其主要特征是它包含抽象成員,抽象成員是沒有實現的方法或屬性,其作用是強制所有派生類提供實現。
is&as
- is操作符可以用來判斷基礎類型,並非僅僅是檢查數據能否成功轉型為目標類型,還會檢查底層對象本身是否是目標類型,如果不是,返回false。
- as嘗試將對象轉換成特定數據類型,當不能轉換的時候,as操作符會返回null。
C#本質論6.0第六章:繼承