Ben*_*ter 1 c# oop polymorphism
我已经找到了很多这方面的实际例子,并且在覆盖或隐藏方法时理解实际输出,但是我正在寻找一些有关为什么会出现这种情况的信息以及为什么C#根据多态性规则允许它时,这不应该被允许 - 至少,就我对多态性的理解而言(这似乎与维基百科/ Webopedia上的标准定义一致).
Class Base
{
public virtual void PrintName()
{
Console.WriteLine("BaseClass");
}
}
Class FirstDerived : Base
{
public override void PrintName()
{
Console.WriteLine("FirstDerived");
}
}
Class SecondDerived : Base
{
public new void PrintName()
{
Console.WriteLine("SecondDerived");
}
}
Run Code Online (Sandbox Code Playgroud)
使用以下代码:
FirstDerived b = new FirstDerived();
BaseClass a = b;
b.PrintName();
a.PrintName();
Run Code Online (Sandbox Code Playgroud)
我明白了:
FirstDerived FirstDerived
好的,我明白了,这很有道理.
SecondDerived c = new SecondDerived();
BaseClass a = c;
c.PrintName();
a.PrintName();
Run Code Online (Sandbox Code Playgroud)
我明白了:
SecondDerived
BaseClass
Run Code Online (Sandbox Code Playgroud)
好吧,这也是有道理的,实例a看不到c.PrintName()所以它使用自己的方法来打印自己的名称,但是我可以使用以下命令将我的实例转换为其真实类型:
((SecondDerived)a).PrintName();
Run Code Online (Sandbox Code Playgroud)
要么
(a as SecondDerived).PrintName();
Run Code Online (Sandbox Code Playgroud)
获得我期望的输出:
SecondDerived
Run Code Online (Sandbox Code Playgroud)
那么在幕后发生了什么,这在多态性方面意味着什么呢?我被告知这个设施"打破了多态性" - 我想根据定义,它确实如此.是对的吗?像C#这样的"面向对象"语言真的会让你打破OOP的核心原则之一吗?
(这回答了"为什么这是允许的",我认为这是你问题的中心点.如何在IL方面起作用我的想法不那么有趣...如果你想让我进入那个,请告诉我基本上,这只是指定使用不同类型令牌调用方法的情况.)
它允许基类在不破坏派生类的情况下进化.
假设Base原来没有这个PrintName方法.得到的唯一方法SecondDerived.PrintName是使用静态类型的表达式SecondDerived,并在其上调用它.您运送产品,一切都很好.
现在快速Base介绍一种PrintName方法.这可能有也可能没有相同的语义SecondDerived.PrintName- 最安全的假设它没有.
任何打电话的人都Base.PrintName知道他们正在调用新方法 - 他们之前无法调用它.以前使用的任何呼叫者SecondDerived.PrintName 仍然想要使用它 - 他们不想突然结束呼叫Base.PrintName,这可能做一些完全不同的事情.
困难是新的呼叫者SecondDerived.PrintName,他们可能会或可能不会意识到这不是一种覆盖Base.PrintName.他们当然可以从文档中注意到这一点,但可能并不明显.但是,至少我们没有破坏现有代码.
当SecondDerived重新编译时,作者将意识到现在有一个Base.PrintName类通过警告.他们可以通过添加new修饰符来坚持现有的非虚拟方案,或者使其覆盖Base.PrintName方法.在他们做出决定之前,他们会不断收到警告.
根据我的经验,OO理论中通常没有提到版本控制和兼容性,但C#旨在避免兼容性噩梦.它并没有完全解决问题,但它做得非常好.