作为一名主要从事Java开发的开发者,有一天我偶然使用了new关键字而不是override,结果让我有些惊讶。
看起来new关键字会在继承树中的那个级别上移除方法的“虚拟性”,因此,在将子类实例向下转换为父类并调用方法时,将不会解析到子类中的方法实现。
这种行为有哪些实际用例?
澄清一点:我理解当父类不是虚拟的时候使用new的用法。我更好奇的是编译器为什么允许new和virtual组合使用。
以下示例说明了差异:
这将产生以下输出:
看起来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
new
,那么编译器会发出警告。这个想法是,如果你明确地添加了一个修饰符,那就意味着你真的是有意为之 :) - Jon Skeet