“只有在‘故意不让父类成员参与多态’,但又不想改父类签名时,才用
new
隐藏继承成员。”一、先分清
表格
关键字 | 目的 | 运行时效果 |
---|---|---|
override |
扩展/替换父类实现 | 动态绑定——真实类型决定方法 |
new |
彻底隐藏父类成员 | 静态绑定——变量声明类型决定方法 |
二、典型使用场景
-
父类成员不是
virtual
/abstract
你无法override
,却又想在子类里用同名签名提供新实现。csharpclass Base {public void Foo() => Console.WriteLine("Base.Foo"); } class Derived : Base {public new void Foo() => Console.WriteLine("Derived.Foo"); }
-
故意切断多态——“只让编译期看变量类型”
例如第三方库升级,父类突然加了非虚方法,与你的子类重名;
用new
可避免编译错误,同时保证老代码继续走旧逻辑。 -
隐藏字段/属性(同样适用)csharp
class A { public int X = 1; } class B : A { public new int X = 2; }
三、代码演示“隐藏 vs 重写”差异
csharp
Base b = new Derived();
b.Foo(); // 输出 Base.Foo ← 隐藏=静态绑定
csharp
Base b2 = new Derived2(); // Derived2 用 override
b2.Foo(); // 输出 Derived2.Foo ← 多态=动态绑定
四、使用 checklist
✅ 父类方法没标
✅ 想故意切断多态,让“变量类型”决定行为 →
✅ 库升级出现同名冲突,又不敢改库源码 →
virtual
→ 只能 new
✅ 想故意切断多态,让“变量类型”决定行为 →
new
✅ 库升级出现同名冲突,又不敢改库源码 →
new
❌ 想让子类实例统一多态 → 用
virtual/override
,千万别 new
五、面试金句
“当父类成员不是虚方法,我又必须在子类用同名签名提供新实现,或者故意不让它参与多态时,就用new
隐藏继承成员;
它与override
的本质区别是——隐藏走编译期类型,重写走运行时类型。”