我有以下课程:
class Base
{
public virtual void Print()
{
Console.WriteLine("Base");
}
}
class Der1 : Base
{
public new virtual void Print()
{
Console.WriteLine("Der1");
}
}
class Der2 : Der1
{
public override void Print()
{
Console.WriteLine("Der2");
}
}
这是我的主要方法:
Base b = new Der2();
Der1 d1 = new Der2();
Der2 d2 = new Der2();
b.Print();
d1.Print();
d2.Print();
输出为Base
,Der2
,Der2
。
据我所知,即使指针指向它们,Override也不会让以前的方法运行。所以第一行也应输出Der2
。但Base
出来了。
怎么可能?覆盖如何在那里不起作用?
答案 0 :(得分:28)
您实际上从未覆盖Base
Print()
版本的Der1
。您只在new
中使用单独的虚拟方法(名称相同)隐藏了它。
当您在方法签名上使用Der2
关键字时 - 您告诉编译器这是一个碰巧与您的某个基类的方法同名的方法 - 但没有其他关系。你可以将这个新方法设为虚拟(就像你已经完成的那样),但这与覆盖基类方法不同。
在Print
覆盖Der1
时,您实际上覆盖了在Base
中声明的“新”版本 - 而不是版本Print
。 Eric Lippert有一个excellent answer到一个稍微不同的问题,可以帮助你推断如何用C#语言处理虚拟方法。
在您的示例中,当您致电Base
时,您通过Print
类型的引用在第一种情况下调用它 - 所以Der1
的隐藏(但不是覆盖)版本叫做。另外两个调用被分派到override
的实现,因为在这种情况下,你实际上已经覆盖了该方法。
您可以在MSDN documentation of new and override。
中详细了解相关信息您可能要对Der1做的事情(就像您对Der2所做的那样)是使用class Base
{
public virtual void Print()
{
Console.WriteLine("Base");
}
}
class Der1 : Base
{
// omitting 'new' and using override here will override Base
public override void Print()
{
Console.WriteLine("Der1");
}
}
关键字:
{{1}}
答案 1 :(得分:6)
这是因为Der1
没有覆盖 Print
,它用一个恰好具有相同名称的全新方法取代它(这是由使用new
关键字引起的。因此,当对象转换为Base
时,它会在Print
中调用Base
;没有覆盖来调用..
答案 2 :(得分:1)
override
将取代之前的方法,但由于您的Der1
类不会覆盖Print()
(它使用阴影,使用VB-ism),因此最重要的版本调用了Base
的{{1}},这恰好是它定义的版本
答案 3 :(得分:0)
正如大家所说,课程Der1
正在取代Print()
而不是覆盖它。要查看此操作,您可以将d1
和d2
设为Base
,然后调用print方法。然后它将返回Base
。
((Base)d2).Print(); //Base