近來想了解下C#4.0的新特性,畢竟平時做項目用的都還是2.0的語法- -。
拿了本高級教程第七版的,新書有愛啊,老習慣將目錄和引文遛一邊先。想著還是都翻把,權當復習和學習。
看到構造函數的時候,雖然之前也是理解過的,但看了後感覺還是有必要筆記下這個過程,當是加深記憶和備忘。
這個知識點重要的就是理解構造函數的創建過程。
看例子:
1 class people
2 {
3 protected string name;
4
5 }
6
7 class mm : people
8 {
9 private int _age;
10
11 public void say()
12 {
13 Console.Write(this._age + "," + base.name);
14 }
15
16 }
17
18 class Program
19 {
20 static void Main(string[] args)
21 {
22 mm mmm = new mm();
23 mmm.say(); //結果是:0, ;
24 Console.ReadLine();
25 }
26 }
例子很簡單,結果也很容易猜到。再改下這個列子:
1 class people
2 {
3 protected string _name;
4
5 private people()
6 {
7
8 }
9 }
10
11 class mm : people
12 {
13 private int _age;
14
15 public void say()
16 {
17 Console.Write(this._age + "," + base._name);
18 }
19
20 }
這樣的話,編譯就出錯了說是:“ConstructorTest.people.people()”不可訪問,因為它受保護級別限制。
原因是第5行我將構造函數私有了。
了解類的初始化過程的就很清楚我為什麼要弄這兩個列子,其實重錯誤信息也可以看出端倪。
我主要就是想說清楚繼承下的多層次結構中對象的初始化過程。
不清楚的看下圖就什麼都清楚了:
當我們執行
1 mm mmm = new mm();
我們知道,構造函數的作用就是在創建實例化對象時初始化自身的數據變量。而上面的例子中,MM在初始化自己的時候會去調他的父類People的構造方法去初始化People,而People要自己又得去調他自身父類的構造函數,這樣一直向上找直到“萬物之源”Object。其實這個也挺好理解的,這就是個階級社會,小弟門弄到吃的先給自己的老二,老二自己不敢吃要先給老大,Obejct就是老大,他先自己吃飽了(自己初始化了),然後在把剩下的給老二(初始化),老二吃剩的給小弟(初始化)。
這個過程是比較好理解的,但是在這個過程中有幾點是需要注意的。
1.若在調用父類的構造函數的時候,父類沒有顯式的構造函數可調的時候,編譯器會為其創建默認構造函數(無參空操作),他的作用是將變量賦空值,就像第一個例子那樣,int類型賦的是0,string的是null。
2.在調用的時候,父類若顯式的寫了構造函數,那麼構造函數的訪問級別必須是子類可以訪問到的(即不能為private)。就像第二個例子,去初始MM的時候,由於MM沒有顯式的構造函數,那麼編譯器就會為其創建一個默認的構造函數,然後他試圖去調用父類的無參構造函數,而這時候由於父類已經有了顯式構造函數所以他不會去創建,但這個構造函數卻是private的,子類無法調用到,所以在這裡創建過程就失敗了,即出錯了。
3.默認下下列的寫法是等價的,但是對於理解的作用是比較有用的。
1 class people
2 {
3 protected string _name;
4 //用base()說明去調他父類構造函數
5 //空構造函數寫不寫:base()是一樣的
6 //但要初始父類中的一些變量,就通過:base(xxx)傳參給父類
7 public people()
8 : base()
9 {
10
11 }
12
13 }
14
15 class mm : people
16 {
17 private int _age;
18
19 public mm()
20 : base()
21 {
22 }
23
24 public void say()
25 {
26 Console.Write(this._age + "," + base._name);
27 }
28
29 }
創建過程就是這樣子,明白了後就可以自己控制繼承下多層結構的初始化過程了。