作为主要的 Java 开发人员,有一天我不小心使用了 new 关键字而不是 override,结果让我感到有点惊讶。
看起来 new 关键字删除了继承树中该级别方法的“虚拟性”,因此在向下转换为父类的子类实例上调用方法, 不会解析到子类中的方法实现。
此行为的实际用例是什么?
澄清:我理解当父级不是虚拟时使用 new。我更好奇为什么编译器允许 new 和 virtual 结合。
下面的例子说明了区别:
using System;
public class FooBar
{
public virtual void AAA()
{
Console.WriteLine("FooBar:AAA");
}
public virtual void CCC()
{
Console.WriteLine("FooBar:CCC");
}
}
public class Bar : FooBar
{
public new void AAA()
{
Console.WriteLine("Bar:AAA");
}
public override void CCC()
{
Console.WriteLine("Bar:CCC");
}
}
public class TestClass
{
public static void Main()
{
FooBar a = new Bar();
Bar b = new Bar();
Console.WriteLine("Calling FooBar:AAA");
a.AAA();
Console.WriteLine("Calling FooBar:CCC");
a.CCC();
Console.WriteLine("Calling Bar:AAA");
b.AAA();
Console.WriteLine("Calling Bar:CCC");
b.CCC();
Console.ReadLine();
}
}
这会产生以下输出:
Calling FooBar:AAA
FooBar:AAA
Calling FooBar:CCC
Bar:CCC
Calling Bar:AAA
Bar:AAA
Calling Bar:CCC
Bar:CCC
最佳答案
用例:
- 今天,您使用第 3 方库并从类
Fruit
派生类Banana
。 - 您在
Banana
中实现了一个名为Peel
的方法。Fruit
中没有Peel
。 - 明天,第 3 方将发布新版本的库,包括一个虚拟的
Fruit.Peel
方法 - 你明天重新编译你的代码。你想覆盖
Fruit.Peel
吗?很可能不是——它可能有完全不同的含义。相反,您可以使用Banana.Peel
隐藏它,并且所有现有代码都像今天一样工作。
换句话说,这主要是为了避免版本控制问题。在 Java 中,您最终会重写 Fruit.peel
,即使您不想这样做,很可能导致难以诊断的错误。
关于c# - C# 允许在虚拟方法上使用 new 的用例是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1472701/