免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
把new、virtual、override說透

把new、virtual、override說透

分類: C#基礎(chǔ) 7897人閱讀 評論(43) 收藏 舉報

我們先看下面一段程序:

  1.     /// <summary>
  2.     /// 父類
  3. /// 作者:周公
  4. /// 首發(fā)地址:http://blog.csdn.net/zhoufoxcn/archive/2008/09/02/2864429.aspx
  5. /// 日期:2008-09-01
  6.     /// </summary>
  7.     public class Father
  8.     {
  9.         public void Run0()
  10.         {
  11.             Console.WriteLine("Father.Run0");
  12.         }
  13.      }
  14.     /// <summary>
  15. /// 子類
  16. /// 作者:周公
  17. /// 首發(fā)地址:http://blog.csdn.net/zhoufoxcn/archive/2008/09/02/2864429.aspx
  18. /// 日期:2008-09-01
  19.     /// </summary>
  20.     public class Son:Father
  21.     {
  22.         public void Run0()
  23.         {
  24.             Console.WriteLine("Son.Run0");
  25.         }
  26. }
  27. class Program
  28.     {
  29.         static void Main(string[] args)
  30.         {
  31.         Father[] fatherList = new Father[2];
  32.             fatherList[0] = new Father();
  33.             fatherList[1] = new Son();
  34.             fatherList[0].Run0();
  35.             fatherList[1].Run0();
  36.     }
  37. }

 

程序的運行結(jié)果是:
Father.Run0

Father.Run0

 

稍微細心的朋友可能發(fā)現(xiàn)在Son類的Run0方法下面有一段棕色的波浪線,當(dāng)我們把鼠標(biāo)放到該下劃線上時,會看到下面的提示編譯程序時在程序的“輸出”窗口也能看到這個警告

MethodDemo.Son.Run0()”隱藏了繼承的成員“MethodDemo.Father.Run0()”。如果是有意隱藏,請使用關(guān)鍵字new。

如圖:

 

然后我們再來第二個版本的Run方法,我們稱之為Run1(),,與第一個版本的區(qū)別是在子類的同名同參(方法名相同,參數(shù)個數(shù)和參數(shù)順序相同,下同)方法前面加上了一個new關(guān)鍵字,代碼如下:

  1.     /// <summary>
  2.     /// 父類
  3.  /// 作者:周公
  4. /// 首發(fā)地址:http://blog.csdn.net/zhoufoxcn/archive/2008/09/02/2864429.aspx
  5. /// 日期:2008-09-01    
  6. /// </summary>
  7.     public class Father
  8.     {
  9.         public void Run1()
  10.         {
  11.             Console.WriteLine("Father.Run1");
  12.         }
  13.      }
  14.     /// <summary>
  15. /// 子類
  16. /// 作者:周公
  17. /// 首發(fā)地址:http://blog.csdn.net/zhoufoxcn/archive/2008/09/02/2864429.aspx
  18. /// 日期:2008-09-01
  19.     /// </summary>
  20.     public class Son:Father
  21.     {
  22.         public new void Run1()
  23.         {
  24.             Console.WriteLine("Son.Run1");
  25.         }
  26. }
  27. class Program
  28.     {
  29.         static void Main(string[] args)
  30.         {
  31.         Father[] fatherList = new Father[2];
  32.             fatherList[0] = new Father();
  33.             fatherList[1] = new Son();
  34.             fatherList[0].Run1();
  35.             fatherList[1].Run1();
  36.     }
  37. }

運行結(jié)果如下:

Father.Run1

Father.Run1

 

我們發(fā)現(xiàn)加上new關(guān)鍵字之后,程序的運行結(jié)果沒有發(fā)生改變。也就是在C#中,如果在子類中有與父類同名同參的方法時,C#會隱式幫你在子類的方法前面添加一個new關(guān)鍵字。

 

我們再寫第三個版本的Run方法,即Run2(),與第一個版本不同的是父類的Run2()方面前面加了一個virtual關(guān)鍵字,表示這是一個虛方法,子類的Run2()除了與第一個版本號不同之外(Run0()改成Run2())沒有什么不同。

程序代碼如下:

  1.     /// <summary>
  2.     /// 父類
  3. /// 作者:周公
  4. /// 首發(fā)地址:http://blog.csdn.net/zhoufoxcn/archive/2008/09/02/2864429.aspx
  5. /// 日期:2008-09-01
  6.     /// </summary>
  7.     public class Father
  8.     {
  9.         public virtual void Run2()
  10.         {
  11.             Console.WriteLine("Father.Run2");
  12.         }
  13.      }
  14.     /// <summary>
  15. /// 子類
  16. /// 作者:周公
  17. /// 首發(fā)地址:http://blog.csdn.net/zhoufoxcn/archive/2008/09/02/2864429.aspx
  18. /// 日期:2008-09-01
  19.     /// </summary>
  20.     public class Son:Father
  21.     {
  22.         public void Run2()
  23.         {
  24.             Console.WriteLine("Son.Run2");
  25.         }
  26. }
  27. class Program
  28.     {
  29.         static void Main(string[] args)
  30.         {
  31.         Father[] fatherList = new Father[2];
  32.             fatherList[0] = new Father();
  33.             fatherList[1] = new Son();
  34.             fatherList[0].Run2();
  35.             fatherList[1].Run2();
  36.     }
  37. }

我們看看程序的運行效果:

Father.Run2

Father.Run2

 

程序運行效果與第一個仍然沒有什么區(qū)別,不過這次子類(Son)的Run2()方法又出現(xiàn)了與Run方法的第一個版本(Run0())一樣的警告:“MethodDemo.Son.Run2()”將隱藏繼承的成員“MethodDemo.Father.Run2()”。若要使當(dāng)前成員重寫該實現(xiàn),請?zhí)砑雨P(guān)鍵字override。否則,添加關(guān)鍵字new。

 

我們再寫第四個版本的Run方法,我們稱之為Run3(),這次父類中Run3()的修飾符與第三個版本相比沒有變化(依然是virtual,虛方法),而子類Son中的Run3()方法與第三個版本相比多了一個override修飾符(這次我們熟悉的那個棕色的波浪線警告沒有了)。代碼如下:

  1.     /// <summary>
  2.     /// 父類
  3. /// 作者:周公
  4. /// 首發(fā)地址:http://blog.csdn.net/zhoufoxcn/archive/2008/09/02/2864429.aspx
  5. /// 日期:2008-09-01
  6.     /// </summary>
  7.     public class Father
  8.     {
  9.         public virtual void Run3()
  10.         {
  11.             Console.WriteLine("Father.Run3");
  12.         }
  13.      }
  14.     /// <summary>
  15. /// 子類
  16. /// 作者:周公
  17. /// 首發(fā)地址:http://blog.csdn.net/zhoufoxcn/archive/2008/09/02/2864429.aspx
  18. /// 日期:2008-09-01
  19.     /// </summary>
  20.     public class Son:Father
  21.     {
  22.         public override void Run3()
  23.         {
  24.             Console.WriteLine("Son.Run3");
  25.         }
  26. }
  27. class Program
  28.     {
  29.         static void Main(string[] args)
  30.         {
  31.         Father[] fatherList = new Father[2];
  32.             fatherList[0] = new Father();
  33.             fatherList[1] = new Son();
  34.             fatherList[0].Run3();
  35.             fatherList[1].Run3();
  36.     }
  37. }

程序的運行結(jié)果如下:

Father.Run3

Son.Run3

 

這次我們發(fā)現(xiàn)程序的運行結(jié)果與前面三次不一樣了,這次盡管我們聲明的對象類型都是Father類(Father數(shù)組裝的自然都是Father類型的引用),但是因為實例化數(shù)組中第二個元素的時候調(diào)用了Son類的構(gòu)造函數(shù),也就是實例化了一個Father類的子類(我們知道子類可以當(dāng)作父類來看待,他們之間是is a的關(guān)系,反之則不行),也就是說fatherList數(shù)組中的第二個元素的引用類型是Father類型,但它的實例類型確實Son類型。而在運行的時候,并不是根據(jù)我們的引用類型(引用類型是Father類型的)去調(diào)用該引用類型的方法,而是調(diào)用該引用類型所指向的實例的方法。

 

為什么會發(fā)生這些現(xiàn)象呢?這里要提到兩個概念:早綁定(early binding)和晚綁定(Late binding)。這個術(shù)語出現(xiàn)在存在繼承關(guān)系的基類和派生類中,它們同時定義了一個同名同參的方法。

早綁定:在編譯的時候就已經(jīng)確定了將來程序運行基類或是派生類的哪個方法。在編譯代碼的時候根據(jù)引用類型就決定了運行該引用類型中定義的方法,即基類的方法。這種方法運行效率高。

晚綁定:只有在運行的時候才能決定運行基類或者派生類中的哪個方法。運行的時候?qū)⒏鶕?jù)該實際類型而不是引用類型來調(diào)用相關(guān)方法,即取決于我們new了什么樣對象。也就是即使我們new一個Father類的子類Son的實例,而不管我們是用Father類的引用指向這個Son的實例,方法調(diào)用的時候依然是調(diào)用Son的方法,而不是Father類的同名方法。

如我們上面所見,為了實現(xiàn)晚綁定,C#引入了兩個關(guān)鍵詞virtual和override。和Java中不同,Java中一切方法都是虛方法,也就是在運行的時候,JVM會自動檢測該引用的類型與實際類型是否一致(無論如何,該引用類型與實際類型之間存在著相等或者繼承關(guān)系,這樣才滿足is a的關(guān)系),如果一致執(zhí)行該類型中定義的方法;如果不一致則會檢查該引用的實際類型是否具有同名同參方法,如果有則運行該實際類型的同名同參方法。這樣會帶來一個問題:每次運行的時候都會進行類型檢查,這樣會帶來一定的性能消耗。而在C#中一切方法如果沒有顯示指明,都是非虛的。對于非虛的方法,CLR運行的時候并不會進行類型檢查,而是直接運行該引用的類型中所定義的方法,即使這個引用所指向的實際類型是該引用類型的派生類,并且在派生類中存在著同名同參的方法,也不會運行派生類中定義的方法。這時,派生類中的方法隱藏了基類中的方法。

但是如果在基類中顯示聲明方法為虛方法,那么CLR在運行的時候會進行類型檢查,如果發(fā)現(xiàn)引用類型和實際的對象類型不一致,就會檢查派生類中是否覆蓋(override)了基類中的方法,如果是,則會運行派生類中的方法,而不是引用類型中的方法。

 

有興趣的朋友還可以看看本人的另一篇文章:《談?wù)凜#中的三個關(guān)鍵詞new , virtual , override》

 

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
淺析繼承關(guān)系中的方法調(diào)用
virtual,override,new學(xué)習(xí) - 永不止步 - 51CTO技術(shù)博客
C#與Java多態(tài)方面的語法差異
重寫與重載的區(qū)別
如何理解父類引用指向子類對象
[轉(zhuǎn)載]C#中的new修飾符以及多態(tài)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服