在类层次结构中,使用 override
和 new
关键字定义方法的区别是什么?
new
会创建一个全新的方法(可能与原方法签名相同,也可能不同),而不是覆盖原有方法(此时新方法必须与原方法具有相同的签名),这意味着多态性将无法发挥作用。例如,你有以下类:
class A {
public virtual int Hello() {
return 1;
}
}
class B : A {
new public int Hello(object newParam) {
return 2;
}
}
class C : A {
public override int Hello() {
return 3;
}
}
如果你这样做:
A objectA;
B objectB = new B();
C objectC = new C();
Console.WriteLine(objectB.Hello(null)); // 2
Console.WriteLine(objectC.Hello()); // 3
objectA = objectB;
Console.WriteLine(objectA.Hello()); // 1
objectA = objectC;
Console.WriteLine(objectA.Hello()); // 3
由于你可以使用new
来定义新的方法签名,因此编译器无法知道A
实例实际上是B
实例,以便让新方法B
可用。当父对象的方法、属性、字段或事件没有声明为virtual
时,可以使用new
,由于缺乏virtual
,编译器不会“查找”继承的方法。但是,使用virtual
和override
就能够解决这个问题。new
;在最好的情况下,它很令人困惑,因为您正在定义一个可能被认为是其他东西的名称的方法,而在最坏的情况下,它可能会隐藏错误、引入看似不可能的错误,并使扩展功能变得困难。看起来这是一个老问题,让我尝试不同的回答:
new
:如其名,它是继承层次结构中的一个新成员,并且如果标记为virtual,则将用作进一步向下链的基础成员。
override
:它意味着我不接受我的父类成员实现,我会做出不同的实现。
using System;
namespace ConsoleApp
{
public static class Program
{
public static void Main(string[] args)
{
Overrider overrider = new Overrider();
Base base1 = overrider;
overrider.Foo();
base1.Foo();
Hider hider = new Hider();
Base base2 = hider;
hider.Foo();
base2.Foo();
}
}
public class Base
{
public virtual void Foo()
{
Console.WriteLine("Base => Foo");
}
}
public class Overrider : Base
{
public override void Foo()
{
Console.WriteLine("Overrider => Foo");
}
}
public class Hider : Base
{
public new void Foo()
{
Console.WriteLine("Hider => Foo");
}
}
}
Overrider => Foo
Overrider => Foo
Hider => Foo
Base => Foo
- 子类通过应用
override修饰符
来覆盖虚方法:- 如果您想有意地
隐藏
一个成员,那么您可以在子类中对该成员应用new修饰符
。new修饰符仅仅是抑制编译器会产生的警告
Program
类和其他类拆分为两个单独的代码块,并将输出与方法调用一起作为注释,例如 base2.Foo(); // Base => Foo
,它将更易读。我还会省略命名空间和导入,但如果您想提供可运行的代码,则只需链接到 https://dotnetfiddle.net/。 - ahongoverride
允许你重写基类中的虚方法,以便你可以放置不同的实现。而new
则会隐藏基类中的非虚方法。
new
则是完全独立的方法,只是恰好具有相同的名称。 - CodesInChaos