在這份筆記之中,我們要來檢測類別繼承的架構下,這些被繼承的建構式的執行順序。
了解更多關於 [C# 和 .NET 中的繼承] 的使用方式
了解更多關於 [C# 程式設計手冊]
了解更多關於 [建構函式]
測設的類別宣告與測試程式
底下列出了我們這測試的三種不同建立類別的情境會用到的 C# 原始碼
namespace ConsoleApp2
{
/// <summary>
/// 祖父級的基礎類別
/// </summary>
public class BaseBaseClass
{
public BaseBaseClass()
{
Console.WriteLine("Call BaseBaseClass() Constructor");
}
}
/// <summary>
/// 父親級的基礎類別
/// </summary>
public class BaseClass : BaseBaseClass
{
public BaseClass()
{
Console.WriteLine("Call BaseClass() Constructor");
}
public BaseClass(string para)
{
Console.WriteLine($"Call BaseClass(\"{para}\") Constructor");
}
}
/// <summary>
/// 衍生類別
/// </summary>
public class DerivedClass : BaseClass
{
public DerivedClass()
{
Console.WriteLine("Call DerivedClass() Constructor");
}
public DerivedClass(string para)
{
Console.WriteLine($"Call DerivedClass(\"{para}\") Constructor");
}
public DerivedClass(string para, int paraInt):base(para)
{
Console.WriteLine($"Call DerivedClass(\"{para}\", \"{paraInt}\") Constructor");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("測試一 new DerivedClass()");
var fooDerivedClassObject = new DerivedClass();
Console.WriteLine("---------------");
Console.WriteLine("測試二 new DerivedClass(some string)");
var fooDerivedClassObjectWithArg = new DerivedClass("Create Derived Class with Argument");
Console.WriteLine("---------------");
Console.WriteLine("測試三 new DerivedClass(some string, some int)");
var fooDerivedClassObjectWith2Arg = new DerivedClass("Create Derived Class with Argument", 2);
Console.WriteLine("Press any key for continuing...");
Console.ReadKey();
}
}
}
類別繼承架構與建構式設計說明
在這裡,我們定義了三個類別
BaseBaseClass
這個類別是在繼承關係中,位於最上層的位置,也就是所有類別的祖先,我在這裡簡稱為基礎基礎類別
在這裡類別中,只有預設建構式,為了要能夠知道程式執行過程中,有呼叫到這個基礎基礎類別
的建構式,所以,我還是把這個預設建構是寫了出來,不過,裡面只有輸出一段訊息到命令提示視窗中。
public BaseBaseClass()
{
Console.WriteLine("Call BaseBaseClass() Constructor");
}
BaseClass
這個類別,繼承了BaseBaseClass
(基礎基礎類別
) ,在這我稱它為基礎類別
在這個基礎類別中,我們定義了兩個建構式,一個是預設建構式,另外一個建構式會接收一個字串參數。會設計這兩個建構式,主要是要測試,當衍生類別沒有特別指定基礎類別要執行的建構式的時候,在基礎類別中,預設建構式會被主動的執行;若在衍生類別的建構式中,有特別指定呼叫的基礎類別的建構式,此時,該基礎類別上的指定符合函式簽章的建構式,就會被執行。
public BaseClass()
{
Console.WriteLine("Call BaseClass() Constructor");
}
public BaseClass(string para)
{
Console.WriteLine($"Call BaseClass(\"{para}\") Constructor");
}
DerivedClass
這個類別,繼承了BaseClass
(基礎類別
),在這裡我稱它為衍生類別在最後的衍生類別中,共宣告了三個種函式簽章的建構式。
public DerivedClass()
{
Console.WriteLine("Call DerivedClass() Constructor");
}
public DerivedClass(string para)
{
Console.WriteLine($"Call DerivedClass(\"{para}\") Constructor");
}
public DerivedClass(string para, int paraInt):base(para)
{
Console.WriteLine($"Call DerivedClass(\"{para}\", \"{paraInt}\") Constructor");
}
建立一個衍生類別的物件,但使用預設建構式
在這個測試中,我們使用了
var fooDerivedClassObject = new DerivedClass();
這個敘述,建立了一個衍生類別
DerivedClass
的物件,此時,在命令提示視窗中會出現底下的訊息。
我底下的訊息中,我們可以得知,
- 當衍生類別的物件被產生的時候,會先呼叫基礎基礎類別的建構式,因為,沒有特別指定要執行哪個基礎基礎類別的建構式,所以,基礎基礎類別的預設建構式 (
BaseBaseClass()
)會先被執行。 - 接著,將會呼叫基礎類別的建構式,因為,沒有特別指定要執行哪個基礎類別的建構式,所以,基礎類別的預設建構式 (
BaseClass()
) 會先被執行。 - 最後,才是衍生類別的建構式 (
DerivedClass()
) 會被執行
執行結果
測試一 new DerivedClass()
Call BaseBaseClass() Constructor
Call BaseClass() Constructor
Call DerivedClass() Constructor
建立一個衍生類別的物件,但使用有字串參數的建構式
在這個測試中,我們使用了,也就是說,當我們要建立一個衍生類別物件的時候,順便將一個字串傳遞到建構式內,當然,我們在這個衍生類別中,就需要宣告多的建構式,並且使用不同的函式簽章,透過多載 (Overloading) 的技術,可以讓使用者選擇不同的建構式函式來建立該類別的物件。
var fooDerivedClassObjectWithArg = new DerivedClass("Create Derived Class with Argument");
在這個建構式
DerivedClass(string para)
中,我僅在呼叫衍生類別的建構式時候,輸出不同的文字內容,而基礎類別與基礎基礎類別,則會延續上個說明程序來執行。 public DerivedClass(string para)
{
Console.WriteLine($"Call DerivedClass(\"{para}\") Constructor");
}
執行結果
測試二 new DerivedClass(some string)
Call BaseBaseClass() Constructor
Call BaseClass() Constructor
Call DerivedClass("Create Derived Class with Argument") Constructor
建立一個衍生類別的物件,指定基礎類別要執行建構式函式
在這個測試中,我們將會在衍生類別的建構適中,指定要執行的基礎類別建構式,底下是我們要建立衍生類別物件的執行程式,在這裡,我們呼叫的衍生類別建構式,需要傳遞一個字串與整數進去。
var fooDerivedClassObjectWith2Arg = new DerivedClass("Create Derived Class with Argument", 2);
在這個衍生類別建構式
DerivedClass(string para, int paraInt)
中,您可以看到,我們有使用了 :base(para)
敘述,指名要執行基礎類別的這個有接收字串參數的建構式。
因此,您可以從下方看到繼承關係的各類別之建構式的執行情況。
public DerivedClass(string para, int paraInt):base(para)
{
Console.WriteLine($"Call DerivedClass(\"{para}\", \"{paraInt}\") Constructor");
}
執行結果
測試三 new DerivedClass(some string, some int)
Call BaseBaseClass() Constructor
Call BaseClass("Create Derived Class with Argument") Constructor
Call DerivedClass("Create Derived Class with Argument", "2") Constructor