簡體   English   中英

c#:調用繼承的基本方法時的控制流,該方法又調用了在派生類中設置為新的基本虛擬方法

[英]c#: flow of control when calling an inherited base method, which inturn calls a base virtual method which is set as new in derived class

免責聲明:我是這個編碼世界的新手! 在學習C#的課程中,我閱讀了這篇文章。 https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords

碼:

public class Car
{
    public void DescribeCar()
    {
        Console.WriteLine("Car: Four wheels and an engine.");
        ShowDetails();
    }

    public virtual void ShowDetails()
    {
        Console.WriteLine("Car: Standard transportation.");
    }
}

public class ConvertibleCar : Car
{
    public new void ShowDetails()
    {
        Console.WriteLine("ConvertibleCar: A roof that opens up.");
    }
}

ConvertibleCar myCC = new ConvertibleCar();
myCC.DescribeCar();
myCC.ShowDetails();

//Output
Car: Four wheels and an engine.
Car: Standard transportation.
ConvertibleCar: A roof that opens

問題:我希望憑自己的理解,我應該在第二行和第三行輸出中看到“ ConvertibleCar:屋頂比開口”。 直接在派生類上以及從基類的方法內部調用ShowDetails時有什么不同。 PS:showdetials在派生類中設置為new。

因為有了new您就可以有效地遮蓋ShowDetails (實際上,在VB.NET中,有一個Shadows關鍵字用於此功能)。 此外,使用new可以使ShadowDetails成為屬性!

讓我們創建兩個類:Base和Derived:

class Base
{
    public virtual int GetInt()
    {
        return 10;
    }
}

class Derived : Base
{
    public new int GetInt()
    {
        return 11;
    }
}

現在,讓我們對其進行測試:

Base b;
Derived d;
int x;

b = new Derived();
d = new Derived();

x = b.GetInt(); // x = 10 [Base.GetInt()]
x = d.GetInt(); // x = 11 [Derived.GetInt()]

如您所見,盡管b被分配了Derived,但它仍然指向Base

但是,讓我們做一些完全不同的事情-讓我們將方法變成屬性!

class Derived : Base
{
    public new int GetInt
    {
        get { return 11; }
    }
}

現在,當我們運行之前的測試代碼時,我們將看到x = 10

x = d.GetInt(); // x = 10

但是,等等, Derived類中沒有GetInt()方法! 為什么要編譯代碼? 很簡單-因為我們用GetInt屬性遮蓋了GetInt()方法, GetInt現在可以從Base調用GetInt() GetInt()困惑的是,IntelliSense並未在d變量上顯示GetInt()方法,但是編譯器很滿意。 要獲得11,您需要調用屬性:

x = d.GetInt;

您還可以將GetInt()方法轉換為委托:

class Derived : Base
{
    public new delegate int GetInt();
}

並使用它:

Derived.GetInt getIntDelegate = () => 12;
Console.WriteLine(getIntDelegate()); // Prints 12

用於隱藏基本成員/方法的new關鍵字。 所以

public new void ShowDetails()
{
    Console.WriteLine("ConvertibleCar: A roof that opens up.");
}

ShowDetails方法是ConvertibleCar類的new方法,基類ShowDetails方法是完全不同的,並且不在繼承鏈中。 想象一下,您可以在ConvertibleCar類中定義類似ShowDetails2的方法名稱。 情況會一樣。

另外,如果使用override keyword而不是newConvertibleCar類將覆蓋ShowDetails方法。

public class ConvertibleCar : Car
{
    public override void ShowDetails()
    {
        Console.WriteLine("ConvertibleCar: A roof that opens up.");
    }
}

輸出將是;

Car: Four wheels and an engine.
ConvertibleCar: A roof that opens.
ConvertibleCar: A roof that opens.

要獲得預期的輸出,請使用override代替new

public override void ShowDetails()
{
    Console.WriteLine("ConvertibleCar: A roof that opens up.");
}

如果使用new ,你遮擋ShowDetails在基類的方法。 這意味着僅當您從派生類變量調用方法時,才使用派生類實現。

override功能有所不同。 如果ShowDetails被覆蓋,則無論變量的類型如何,只要對象的基礎類型是派生類,就將始終使用派生類實現。

這解釋了為什么第二行輸出不同。 第二行是從此行產生的:

public void DescribeCar()
{
    Console.WriteLine("Car: Four wheels and an engine.");
    ShowDetails(); <--------
}

ShowDetails表示this.ShowDetails thisCar類型,但實際上是指ConvertibleCar的對象。 由於ShowDetails處於陰影中,因此它將調用Car的實現(因為thisCar類型!)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM