構造器在繼承時需要特別的注意,為了保證父類成員變量的正確初始化,子類的任何構造器默認的都必須調用父類的某一構造器,具體調用哪個構造器要看構造器的初始化參數列表。如果沒有初始化參數列表,那麼子類的該構造器就調用父類的無參數構造器;如果有初始化參數列表,那麼子類的該構造器就調用父類對應的參數構造器。看下面例子的輸出:
using System;
public class MyClass1
{
public MyClass1()
{
Console.WriteLine("MyClass1 Parameterless Contructor!");
}
public MyClass1(string param1)
{
Console.WriteLine("MyClass1
Constructor Parameters : "+param1);
}
}
public class MyClass2:MyClass1
{
public MyClass2(string param1):base(param1)
{
Console.WriteLine("MyClass2
Constructor Parameters : "+param1);
}
}
public class Test
{
public static void Main()
{
MyClass2 myobject1=new MyClass2("Hello");
}
}
編譯程序並運行可以得到下面的輸出:
MyClass1 Constructor Parameters : Hello
C#支持變量的聲明初始化。類內的成員變量聲明初始化被編譯器轉換成賦值語句強加在類的每一個構造器的內部。那麼初始化語句與調用父類構造器的語句的順序是什麼呢?看下面例子的輸出:
MyClass2 Constructor Parameters : Hello
using System;
public class MyClass1
{
public MyClass1()
{
Print();
}
public virtual void Print() {}
}
public class MyClass2: MyClass1
{
int x = 1;
int y;
public MyClass2()
{
y = -1;
Print();
}
public override void Print()
{
Console.WriteLine("x = {0}, y = {1}", x, y);
}
}
public class Test
{
static void Main()
{
MyClass2 MyObject1 = new MyClass2();
}
}
編譯程序並運行可以得到下面的輸出:
x = 1, y = 0
x = 1, y = -1
容易看到初始化語句在父類構造器調用之前,最後執行的才是本構造器內的語句。也就是說變量初始化的優先權是最高的。
我們看到類的構造器的聲明中有public修飾符,那麼當然也可以有protected/private/ internal修飾符。根據修飾符規則,我們如果將一個類的構造器修飾為private,那麼我們在繼承該類的時候,我們將不能對這個private的構造器進行調用,我們是否就不能對它進行繼承了嗎?正是這樣。實際上這樣的類在我們的類內的成員變量都是靜態(static)時,而又不想讓類的用戶對它進行實例化,這時必須屏蔽編譯器為我們暗中添加的構造器(編譯器添加的構造器都為public),就很有必要作一個private的實例構造器了。protected/internal也有類似的用法。