当继承一个被继承的类时,新的/覆盖的行为不是我所期望的:
$ cat Program.cs
using System;
class A {
public virtual void SayHi() {
Console.WriteLine("From A");
}
}
class B : A {
public new virtual void SayHi() {
Console.WriteLine("From B");
}
}
class C : B {
public override void SayHi() {
Console.WriteLine("From C");
}
}
public class Program {
public static void Main() {
A p = new C();
p.SayHi();
}
}
$ ./Program.exe
From A
由于 C 类重写了 sayHi() 方法,我希望输出是 From C
。为什么 B 类的 new
修饰符在这里优先?它的用例是什么?特别是因为它打破了让 C 真正覆盖 A 的明显用例。
请注意,上面的代码是在 Mono 2.10 上运行的,Mono 2.10 是在 Debian 派生的发行版上运行的。但我已经在 MS Visual Studio 中使用 C# 编译器确认了相同的行为。
最佳答案
new
modifier导致成员隐藏,这会破坏类层次结构中的多态关系。 B
的 SayHi
方法被视为与 A
的不同(而不是覆盖)(因此选择"new"一词作为关键字)。 C
的方法然后覆盖 B
的方法,而不是 A
的方法(它仍然隐藏)。
因此,当您通过 A
引用在 C
实例上调用 SayHi
时,运行时将根据 A 解析它
类型,而不是 C
类型(其中 SayHi
是从 B
继承的"new"方法)。
另一方面,如果您要运行:
B p = new C();
p.SayHi();
……你会得到预期的多态结果:
From C
编辑:由于您请求了一个用例,这里有一个。在 .NET Framework 2.0 中引入泛型之前,成员隐藏有时被用作更改派生类中继承方法的返回类型的一种方法(重写时不能这样做)以返回更具体的类型。例如:
class ObjectContainer
{
private object item;
public object Item
{
get { return item; }
set { item = value; }
}
}
class StringContainer : ObjectContainer
{
public new virtual string Item
{
get { return base.Item as string; }
set { base.Item = value as string; }
}
}
class QuotedStringContainer : StringContainer
{
public override string Item
{
get { return "\"" + base.Item + "\""; }
}
}
ObjectContainer
类的Item
属性返回一个普通的对象
。但是,在 StringContainer
中,这个继承的属性被隐藏以返回一个 string
。因此:
ObjectContainer oc = new StringContainer();
object o = oc.Item; // Valid, since ObjectContainer.Item is resolved
string s1 = oc.Item; // Not valid, since ObjectContainer.Item is still resolved
string s2 = ((StringContainer)oc).Item;
// Valid, since StringContainer.Item is now resolved
QuotedStringContainer
类覆盖了StringContainer
的Item
属性,继承了它的string
返回类型;但是,它仍然对 object
隐藏 - 返回 ObjectContainer
的 Item
属性。如果不是这样,就没有办法协调它们不同的返回类型……
ObjectContainer oc = new QuotedStringContainer();
object o = oc.Item; // Valid, since ObjectContainer.Item is resolved
string s1 = oc.Item; // Not valid, since ObjectContainer.Item is still resolved
string s2 = ((StringContainer)oc).Item;
// Valid, since QuotedStringContainer.Item is now resolved
// (polymorphism!)
string s3 = ((QuotedStringContainer)oc).Item;
// Valid, since QuotedStringContainer.Item is now resolved
关于c# - 这种继承特性的用例是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11039414/