在面向對象編程中,有兩種截然不同的繼承方式:實現繼承和接口繼承。在實現繼承時候,在Java中,所有函數默認都是virtual的,而在C#中所有函數並不默認為virtual的,但可以在基類中通過聲明關鍵字virtual,就可以在其派生類中通過關鍵字override重寫該函數。
重寫后的virtual函數依舊是virtual函數。由於virtual只對類中的實例函數成員有意義,所以成員字段和靜態函數都不能聲明為virtual,也不能與override和abstract一起用。C#中可以設置virtual屬性、索引器或事件,例如
virtual string Name
{
get;
set;
}
無virtual和override關鍵字“重寫”
如果簽名后的函數在基類中都進行了聲明,卻沒有用virtual和override關鍵字,例如:
class Base1
{
public void printMethod()
{
Console.WriteLine("base1");
}
}
class Derived1 : Base1
{
public void printMethod()
{
Console.WriteLine("derived1");
}
}
class Program
{
static void Main(string[] args)
{
Base1 base1 = new Base1();
Derived1 derived = new Derived1();
base1.printMethod();
derived.printMethod();
base1 = new Derived1();
base1.printMethod();
Console.ReadLine();
}
}
輸出為:
base1
derived1
base1
由於方法相同,在用子類新方法編譯代碼時候,程序在應該調用哪種方法上就會有潛在的沖突,此時編譯器會發出警告,認為子類Derived1的printMethod()隱藏了父類Base1的printMethod();此時可以從新命名子類Derived1的printMethod(),這是最好的解決辦法,其次可以通過關鍵字new隱藏此方法來控制版本。
這是所謂的無virtual和override的“重寫”其實只是隱藏。
有virtual和override關鍵字“重寫”
在派生類中添加關鍵字virtual和override,實現對基類的重寫:
class Base1
{
public virtual void printMethod()
{
Console.WriteLine("base1");
}
}
class Derived1 : Base1
{
public override void printMethod()
{
Console.WriteLine("derived1");
}
}
class Program
{
static void Main(string[] args)
{
Base1 base1 = new Base1();
Derived1 derived = new Derived1();
base1.printMethod();
derived.printMethod();
base1 = new Derived1();
base1.printMethod();
Console.ReadLine();
}
}
此時,輸出的結果是:
base1
derived1
derived1
在類的定義中,申明時定義的類叫申明類,執行實例化時候定義的類叫實例類。例如:
Base1 base1 = new Derived1 ();其中Base1叫做申明類,而Derived1則是實例類。
此時編譯器具體的檢查的流程如下
1、當調用函數時,系統會直接去檢查申明類,看所調用的函數是否為虛函數;
2、如果不是,那么它就直接執行該函數。如果是virtual函數,則轉去檢查對象的實例類。
3.在實例類中,若有override的函數,則執行該函數,如果沒有,則依次上溯,按照同樣步驟對父類進行檢查,知道找到第一個override了此函數的父類,然后執行該父類中的函數。(星夢《C#虛函數virtual詳解收藏》)
由此可知,
若子類Derived1中未添加關鍵字override,則直接在base1中執行父類同名函數,此時輸出結果為:
base1
derived1
base1
依次類推,若有Derived2繼承了Derived1,即:
class Derived2 : Derived1
{
public void printMethod(){
Console.WriteLine("derived2");
}
}
在Program類 中執行
base1 = new Derived2();
base1.printMethod();
則此時執行的是Derived2中override的同名函數printMethod()。
---------------------
作者:songsz123
來源:CSDN
原文:https://blog.csdn.net/songsz123/article/details/7369913
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!