C# 繼承
繼承的語法
a、在兒子類的類名后面 寫上一個冒號 再跟上父親類的名字。
a、在兒子類的類名后面 寫上一個冒號 再跟上父親類的名字。
calss Student:Person 子類:父類
1 class Person 2 { } 3 4 class Student : Person 5 { }
b、Student 類從Person類繼承,Student類是Person類的子類。Person類是Student類的父類。
Student 類從Person類派生,Student類是Person類的派生類。Person類是Student類的基類。
子類從父類繼承,那么子類就擁有父類的全部成員。
繼承的特點
a、單根性:一個類只能有1個父類。但是一個類可以實現多個接口。
b、Object類是所有類的基類。C#中的類都直接的或者間接的從Object類繼承。
如果我們寫一個類,不為這個類指定父類,那么這個類默認就從object類繼承。所以我們才可以在這個類中看到object類的成員。
c、傳遞性:A類從B類繼承,B類從C類繼承,那么A類就擁有了B和C的所有的成員。
在創建子類對象的時候,會去調用父類的構造函數。
a、先調用子類的構造函數
b、再調用父類的構造函數
c、再執行父類的構造函數
d、再執行子類的構造函數
調用父類的構造函數為當前對象的子類對象的父類成員賦值
父類的屬性放在父類的構造函數中初始化。而子類對象中擁有自己的屬性和從父類繼承過來的屬性,我們要為子類寫一個構造函數,用於初始化子類的所有屬性,
a、直接寫一個子類構造函數會去調用父類的無參數的構造函數。所以父類如果如果無參數的構造函數的話,要為父類添加一個。
b、將父類的屬性的值交給父類的構造函數去初始化。子類構造函數只初始化自己的屬性。此時,如果子類構造函數調用父類的構造函數,在父類的構造函數中訪問的成員不是父類對象的,是當前子類對象中的父類成員
補充
1、結構體是不能夠繼承的,但是可以實現接口。
但是所有的結構體都默認從ValueType這個類繼承。而ValueType這個類又從Object繼承,根據繼承的傳遞性,所以我們的結構體對象中就擁有Object類的成員。
2、子類的訪問級別不能比父類高
3、靜態類是不能被繼承的
a、靜態類不能相互繼承,因為靜態類沒有實例構造函數
b、靜態類默認直接從Object去繼承
c、靜態類的本質其實是一個密封類。
4、在子類中可以存在和父類中的同名方法,如果方法的參數的個數或者類型不同,那么他們子類中構成重載。
5、在子類對象中是可以存在和父類相同的成員。
- 創建父類對象,通過父類對象調用這個同名成員,毫無疑問調用的是父類的。
- 創建子類對象,通過子類對象調用這個同名成員,調用的是子類自己獨有的。
- 子類中的同名成員會將父類的同名成員覆蓋掉,所以我們通過子類對象來調用同名成員的時候,它調用的是子類的同名成員。
- 請記住,通過子類對象是無論如何也調用不到同名的父類成員,因為子類的同名成員將父類的同名成員覆蓋掉了。但是在子類的內部,仍然是可以通過base關鍵字調用到父類的同名成員。
問題
Q1:子類從父類繼承,子類就可以擁有父類的全部成員嗎?
a、在子類中,可以訪問父類的public 和internal 不能訪問private。
b、子類從父類繼承,那么子類模版中就擁有了父類模版中的所有成員,包括私有成員。在創建子類對象的時候,因為子類對象是根據子類模版創建的,所以子類對象當中自然也就有父類的私有成員。只不過父類的私有成員,在子類的內部無法訪問,但是它卻真實的存在。
c、類的成員的訪問修飾符
public:可以在任意地方訪問
private:只能在類的內部訪問
internal:可以在當前程序集訪問
protected:可以在本類的和本類的子類中訪問。
d、子類從父類繼承,子類模版中就擁有了父類模版中的所有成員,包括私有的。只不過在子類的內部只能訪問父類的 非私有成員。
Q2:為什么創建子類對象的時候要去調用父類的構造函數呢?
因為父類的字段的初始化是放在父類的構造函數中。如果創建子類對象的時候不去調用父類的構造函數,那么創建完這個子類對象以后,這個子類對象中從父類繼承過來的字段就沒有默認值。
默認情況下,子類的構造函數會去調用父類的無參數的構造函數。但是如果父類沒有無參數的構造函數,那么我們要通過base關鍵字為子類構造函數指定要調用父類的哪一個構造函數。
語法:
public 子類():base()
{}
在base的小括弧中通過實參的個數和類型去匹配父類的構造函數。