场景#1:
假设您正在设计 .NET 2.0 的运行时库。您现在可以使用仿制药。你有一个界面:
interface IEnumerable
{
IEnumerator GetEnumerator();
}
您希望制作一个新界面
interface IEnumerable<T>
{
IEnumerator<T> GetEnumerator();
}
您现在有三个选择。
1) 使通用版本与非通用版本无关。
2) 使通用版本扩展非通用版本。现在您有两种方法,它们仅在返回类型上有所不同。将新类型中的 GetEnumerator 名称更改为 GetEnumerator2()。因为那很热。每个人都喜欢好的“2”方法。
3) 使通用版本扩展非通用版本。使新的和改进的方法隐藏现有方法,以便在需要时它就在那里,但默认情况下是隐藏的。
这些都是糟糕的选择。你会选择哪个?我们选择了(3)。幸好这是一个选择;如果不隐藏,这个选项就不可能实现。
现在,你可能会争辩说,这个特殊的隐藏例子“不值得”;如果是这样,你会怎么做?
方法隐藏使得在类型系统改进时可以公开改进的接口,而不会造成破坏。
场景#2:
你在 FrobeCo 工作。您生成一个扩展 Blobber 的 Frobber 类,该类是由 BlobCo 的优秀人员提供给您的。
BlobCo 忽略了在 Blobber 上放置 Frobozzle() 方法,但您的客户喜欢使用 frobozzle frobber,因此您向派生类 Frobber 添加了方法 Frobozzle()。
BlobCo 意识到他们的客户想要 Frobozzle blobber,因此他们向基类 Blobber 添加了一个非虚方法 Frobozzle()。
现在你做什么,FrobCo 员工?
1) 删除 Frobber 上的 Frobozzle 方法,从而破坏依赖您实施的客户。请记住,BlobCo 不知道如何 Frobozzle 一个 Frobber;他们只编写了知道如何 Frobozzle Blobber 的代码。
2) 向 BlobCo 抱怨他们应该将他们的方法设为虚拟。希望他们有一天能为此做点什么。
3)在派生类中隐藏它们的方法。
方法隐藏有助于缓解脆弱的基类问题。
进一步阅读:
http://blogs.msdn.com/ericlippert/archive/2008/05/21/method-hiding-apologia.aspx http://blogs.msdn.com/ericlippert/archive/2008/05/21/method-hiding-apologia.aspx