欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#子類對基類方法的繼承、重寫與隱藏詳解

 更新時間:2020年07月26日 09:20:09   作者:老胡寫代碼  
這篇文章主要介紹了C#子類對基類方法的繼承、重寫與隱藏的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用C#具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧

前言

提起子類、基類和方法繼承這些概念,肯定大家都非常熟悉。畢竟,作為一門支持OOP的語言,掌握子類、基類是學習C#的基礎。不過,這些概念雖然簡單,但是也有一些初學者可能會遇到的坑,我們一起看看吧。

子類繼承基類非私有方法

首先我們看最簡單的一種,子類繼承自基類,但子類對繼承的方法沒有任何改動

class Person
{
 public void Greeting()
 {
 Console.WriteLine("Hello, I am Person");
 }
}

class Employee : Person
{

}

class Program
{
 static void Main(string[] args)
 {
 Person p = new Employee();
 p.Greeting();
 }
}

在這個例子中,作為子類的Employee自動繼承了基類的Greeting方法,當在子類實例調用這個方法的時候,實際上調用的是基類的方法。這個例子非常簡單,毋庸多言。 

子類覆蓋基類方法

接著是最常見的情況,子類覆蓋基類的方法,典型的例子如下

class Person
{
 public virtual void Greeting()
 {
 Console.WriteLine("Hello, I am Person");
 }
}

class Employee : Person
{
 public override void Greeting()
 {
 Console.WriteLine("Hello, I am Employee");
 }
}

class Program
{
	static void Main(string[] args)
	{
		Employee e = new Employee();
		Person p = e;
		p.Greeting();
		e.Greeting();
	}
}

同樣,這段代碼也很簡單,基類方法通過關鍵字virtual表明方法可以被覆蓋,子類通過關鍵字override實現對基類方法的覆蓋,最后看調用部分,無論變量類型是子類還是基類,只要對象實際類型是子類,調用的方法都是子類覆蓋的方法,這也是多態(tài)的實現基礎。 

子類隱藏基類方法

上面兩個例子都非常簡單,邏輯也很清楚,有點繞的要算子類隱藏基類方法的情況。

子類隱藏基類的非虛方法

基類被子類繼承的方法可能是虛方法,也可能是非虛方法,先看非虛方法被子類隱藏的情況,隱藏基類方法使用的關鍵字是new

class Person
{
 public void Greeting()
 {
 Console.WriteLine("Hello, I am Person");
 }
}

class Employee : Person
{
 public new void Greeting()
 {
 Console.WriteLine("Hello, I am Employee");
 }
}

class Program
{
 static void Main(string[] args)
 {
 Employee e = new Employee();
 Person p = e;
 p.Greeting();
 e.Greeting();
 }
}

這里的結果可能就出乎某些初學者的意料了,為什么明明是子類Employee的實例,卻在不同的引用變量類型下呈現出了不一樣的效果?為什么會調用到了基類里面的方法?
其實這跟C#的函數調用機制有關,一般來說,C#編譯成MSIL之后,有兩種函數調用方式。

  • Call 以非虛的方式調用方法,一般用于靜態(tài)函數調用,因為靜態(tài)函數不可能是虛的,但也可以以非虛的方式調用一個虛方法
  • Callvirt 以虛方式調用,一般用于非靜態(tài)方法和虛方法的調用。如果調用的方法非虛,則引用變量類型決定了最終調用的方法;反之,如果調用的方法為虛,則實例變量類型決定最終調用的方法——因為可能出現方法重寫,即,多態(tài)

用ILDASM打開我們的程序集看看,

證明了這里確實是用的Callvirt,而這個方法是非虛的方法,所以在兩次調用中,引用變量類型Person和Employee就能夠決定所調用的方法。兩個類分別實現了自己的Greeting方法,沒有出現子類覆蓋基類方法的情況。這就解釋了為什么兩次調用結果不同。最后讓我們來看看最復雜的一種情況 

子類隱藏基類的虛方法

考慮下面的代碼

class Person
{
 public virtual void Greeting()
 {
  Console.WriteLine("Hello, I am Person");
 }
}

class Employee : Person
{
 public new virtual void Greeting()
 {
  Console.WriteLine("Hello, I am Employee");
 }
}

class Manager : Employee
{
 public override void Greeting()
 {
  Console.WriteLine("Hello, I am Manager");
 }
}

class Program
{
 static void Main(string[] args)
 {
  Manager m = new Manager();
  Person p = m;
  Employee e = m;
  p.Greeting();
  e.Greeting();
  m.Greeting();
 }
}

猜一下輸出應該是什么?這也是老胡曾經遇到過的一道筆試題,表面看著簡單,但是不注意也會掉坑里

1,2,3,答案揭曉

是不是有點出乎意料呢,讓我們來分析一下

首先,三次調用均是callvirt,而且方法Greeting是虛方法,我們需要考慮對象實例以決定要調用的方法。

  • 在第一次調用中,引用變量類型是Person,雖然對象實例類型Manger重寫了Greeting方法,但是它重寫的是繼承自Manger基類Emplyee的Greeting方法,Person中Greeting方法在子類Manger中僅僅是被隱藏而沒有被重寫,所以這里調用的是Person中的Greeting
  • 而第二次調用中,引用變量類型是Employee,Employee的Greeting方法被Manager重寫,所以這次調用到的是Manager中的Greeting
  • 最后一次調用毋庸多言,簡單的重寫案例而已

怎么樣,是不是有小伙伴猜錯結果了? 

總結

在子類對基類有方法繼承、重寫和隱藏的情況下,有時候判斷具體哪個方法被調用會有難度,但請記住以下要點:

如果被調用方法非虛,那么只用關注引用變量類型就好,引用變量類型能決定調用方法在哪里如果調用方法為虛,我們需要站在引用變量類型的角度,審視該方法是否被對象類型所重寫;若是,則調用對象類型的重寫方法;反之,則再次讓引用變量類型決定調用方法。

這樣,當我們再遇到子類隱藏基類虛方法的情況,應用以上要點就可以撥云見日。

到此這篇關于C#子類對基類方法的繼承、重寫與隱藏的文章就介紹到這了,更多相關C#子類對基類方法繼承、重寫與隱藏內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C# Chart繪制簡單圖形波形

    C# Chart繪制簡單圖形波形

    這篇文章主要為大家詳細介紹了C# Chart繪制簡單圖形波形,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C# 并發(fā)控制框架之單線程環(huán)境下實現每秒百萬級調度

    C# 并發(fā)控制框架之單線程環(huán)境下實現每秒百萬級調度

    本文介紹了一款專為工業(yè)自動化及機器視覺開發(fā)的C#并發(fā)流程控制框架,通過模仿Go語言并發(fā)模式設計,支持高頻調度及復雜任務處理,已在多個項目中驗證其穩(wěn)定性和可靠性
    2024-10-10
  • Unity3D實現鼠標控制旋轉轉盤

    Unity3D實現鼠標控制旋轉轉盤

    這篇文章主要為大家詳細介紹了Unity3D實現鼠標控制旋轉轉盤,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • C#中DateTime的時間加減法操作小結

    C#中DateTime的時間加減法操作小結

    本文主要介紹了C#中DateTime的時間加減法操作小結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • C#編程之AOP編程思想

    C#編程之AOP編程思想

    這篇文章介紹了C#編程之AOP編程思想,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • C#中使用FilleStream實現視頻文件的復制功能

    C#中使用FilleStream實現視頻文件的復制功能

    這篇文章主要介紹了C#中使用FilleStream實現視頻文件的復制功能,本文通過實例代碼給大家介紹的非常想詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09
  • C# 格式化字符首字母大寫的方法

    C# 格式化字符首字母大寫的方法

    這篇文章介紹了C# 格式化字符首字母大寫的方法,有需要的朋友可以參考一下
    2013-08-08
  • C#使用stackalloc分配堆棧內存和非托管類型詳解

    C#使用stackalloc分配堆棧內存和非托管類型詳解

    這篇文章主要為大家介紹了C#使用stackalloc分配堆棧內存和非托管類型詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪<BR>
    2022-12-12
  • Unity的IPreprocessBuild實用案例深入解析

    Unity的IPreprocessBuild實用案例深入解析

    這篇文章主要為大家介紹了Unity的IPreprocessBuild實用案例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • C#實現圖片上傳(PC端和APP)保存及 跨域上傳說明

    C#實現圖片上傳(PC端和APP)保存及 跨域上傳說明

    這篇文章主要介紹了C#實現圖片上傳(PC端和APP)保存及 跨域上傳說明的相關資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-12-12

最新評論