我有这段代码:
using System;
namespace Test
{
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
Bar bar = new Bar();
Baz baz = new Baz();
Foo fooBar = new Bar();
Foo fooBaz = new Baz();
Bar barBaz = new Baz();
foo.Test();
bar.Test();
baz.Test();
fooBar.Test();
fooBaz.Test();
barBaz.Test();
Console.ReadLine();
}
}
internal class Foo
{
public virtual void Test()
{
Console.WriteLine("Foo");
}
}
internal class Bar : Foo
{
public new virtual void Test()
{
Console.WriteLine("Bar");
}
}
internal class Baz : Bar
{
public override void Test()
{
Console.WriteLine("Baz");
}
}
}
它输出了我:
Foo
Bar
Baz
Foo
Foo
Baz
但是,我认为应该是:
Foo
Bar
Baz
Foo
Baz
Baz
因为Baz压倒了这个方法。这里发生了什么? 我错过了什么吗?为什么fooBaz.Test()的输出是“Foo”而不是“Baz”?
答案 0 :(得分:5)
Buz
覆盖了该方法,这就是
Bar barBaz = new Baz();
barBaz.Test();
将打印Baz
。
但是Bar
没有覆盖 - 它隐藏基本方法Test
并使新方法成为虚拟。然后Baz
将覆盖Bar
中的新方法,而不是来自Foo
的方法。
因此,如果您像这样引用它:Foo fooBaz = new Baz();
则fooBaz
被视为Foo
的实例,它不知道隐藏方法。
如果您将public new virtual void Test()
更改为public override void Test()
,则会生成您期望的输出。
另见这些主题:
答案 1 :(得分:2)
当您在Bar.Test
上使用新关键字时,您说它与Foo.Test
无关,只是它具有相同的名称。由于Baz继承自Bar,它会覆盖Bar.Test
,但不会修改Foo.Test
。
当您致电fooBaz.Test
时,它会查找未经修改的Foo.Test
方法并打印" Foo"。
当您致电barBaz.Test
时,它会查找覆盖Bar.Test
方法并打印" Baz"。