繁体   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