考虑:
public class baseClass{ public void WriteNum() { Console.WriteLine(12); } public virtual void WriteStr() { Console.WriteLine("abc"); }}public class DerivedClass : baseClass{ public new void WriteNum() { Console.WriteLine(42); } public override void WriteStr() { Console.WriteLine("xyz"); }}baseClass isReallybase = new baseClass();baseClass isReallyDerived = new DerivedClass();DerivedClass isClearlyDerived = new DerivedClass();isReallybase.WriteNum(); // writes 12isReallybase.WriteStr(); // writes abcisReallyDerived.WriteNum(); // writes 12isReallyDerived.WriteStr(); // writes xyzisClearlyDerived.WriteNum(); // writes 42isClearlyDerived.writeStr(); // writes xyz覆盖是经典的OO方法,在这种方法中,派生类可以具有比基类更具体的行为(在某些语言中,您别无选择,只能这样做)。在对象上调用虚拟方法时,将调用该方法的最新派生版本。因此,即使我们正在处理
isReallyDerived的
baseClass定义,然后功能
DerivedClass被使用。
隐藏意味着我们拥有完全不同的方法。当我们调用时
WriteNum(),
isReallyDerived就无法知道存在不同之处
WriteNum(),
DerivedClass因此不会被调用。当我们正在处理的对象时,它只能被称为
是 一个
DerivedClass。
大多数时候,隐藏是不好的。通常,如果某个方法可能会在派生类中更改,则应该将其设为虚拟方法,然后在派生类中对其进行覆盖。但是,有两点有用:
前向兼容性。如果
DerivedClass
有一个DoStuff()
方法,然后又baseClass
更改为添加一个DoStuff()
方法,(请记住它们可能是由不同的人编写的,并且存在于不同的程序集中),则禁止成员隐藏的操作可能会突然变成DerivedClass
没有更改的错误。另外,如果新的DoStuff()
onbaseClass
是虚拟的,则在对其DerivedClass
进行覆盖时自动进行设置可能会导致在不应该调用现有方法的情况下对其进行调用。因此,默认为隐藏是很好的(我们用来new
明确表示我们肯定要隐藏,但是将其保留为隐藏并在编译时发出警告)。穷人的协方差。考虑一个返回新值的
Clone()
方法,baseClass
该方法baseClass
是所创建方法的副本。在覆盖上,DerivedClass
这将创建一个,DerivedClass
但将其返回为baseClass
,这没有什么用处。我们可以做的是拥有一个CreateClone()
被覆盖的虚拟保护。在baseClass
我们有一个Clone()
返回此结果的-并且一切都很好-DerivedClass
我们用一个新的Clone()
返回a的隐藏它DerivedClass
。调用Clone()
上baseClass
总是会返回一个baseClass
参考,这将是一个baseClass
价值或DerivedClass
价值合适。调用Clone()
上DerivedClass
会返回一个DerivedClass
值,这是我们在这种情况下想要的。此原理还有其他变体,但是应该注意,它们都很少见。
在第二种情况下要注意的重要一点是,我们已经使用隐藏精确地 消除
了调用代码的意外之处,因为使用该代码的人
DerivedClass可能会合理地期望其
Clone()返回
DerivedClass。可以用任何方式调用的结果都保持一致。大多数隐藏风险的案例都会带来惊喜,这就是为什么人们通常对此不以为然。这样做是正当的,因为它解决了隐藏经常引入的问题。
总而言之,隐藏有时是必需的,很少有用,但通常是不好的,因此要非常警惕。


![覆盖与方法隐藏[重复] 覆盖与方法隐藏[重复]](http://www.mshxw.com/aiimages/31/373332.png)
