Dan*_*May 68 .net c# oop polymorphism inheritance
我最近得到了以下代码作为一种帮助理解Polymorphism
和Inheritance
在OOP - C#中的谜题.
// No compiling!
public class A
{
public virtual string GetName()
{
return "A";
}
}
public class B:A
{
public override string GetName()
{
return "B";
}
}
public class C:B
{
public new string GetName()
{
return "C";
}
}
void Main()
{
A instance = new C();
Console.WriteLine(instance.GetName());
}
// No compiling!
Run Code Online (Sandbox Code Playgroud)
现在,在与提出拼图的其他开发者进行了长时间的长时间聊天后,我知道输出是什么,但我不会为你破坏它.我真正遇到的唯一问题是我们如何得到输出,代码如何逐步通过,继承什么等等.
我认为C
会返回,因为它似乎是定义的类.然后我通过我的脑袋了解是否B
会因为C继承而返回B
- 但B
也继承A
(这是我困惑的地方!).
任何人都可以解释多态性和继承如何在检索输出中发挥作用,最终显示在屏幕上?
Eri*_*ert 97
考虑这一点的正确方法是想象每个类都要求其对象具有一定数量的"槽"; 那些插槽充满了方法.问题是"实际调用什么方法?" 要求你弄清楚两件事:
让我们从考虑插槽开始.有两个插槽.A的所有实例都需要有一个我们称之为GetNameSlotA的插槽.C的所有实例都需要有一个我们称之为GetNameSlotC的插槽.这就是"新"在C语言中的含义 - 它意味着"我想要一个新的插槽".与B中声明的"覆盖"相比,这意味着"我不想要新的插槽,我想重新使用GetNameSlotA".
当然,C继承自A,因此C还必须有一个插槽GetNameSlotA.因此,C的实例有两个插槽 - GetNameSlotA和GetNameSlotC.非C的A或B实例有一个插槽GetNameSlotA.
现在,当你创建一个新的C时,这两个插槽是什么?有三种方法,我们称之为GetNameA,GetNameB和GetNameC.
A的声明说"把GetNameA放在GetNameSlotA中".A是C的超类,因此A的规则适用于C.
B的声明说"把GetNameB放在GetNameSlotA中".B是C的超类,因此B的规则适用于C的实例.现在我们在A和B之间存在冲突.B是更多派生类型,因此它胜出--B的规则优先于 A的规则.因此声明中的"覆盖"一词.
C的声明说"把GetNameC放在GetNameSlotC中".
因此,您的新C将有两个插槽.GetNameSlotA将包含GetNameB,GetNameSlotC将包含GetNameC.
我们现在已经确定了什么方法在哪些插槽中,所以我们已经回答了我们的第一个问题.
现在我们必须回答第二个问题.叫什么插槽?
想想它就像你是编译器一样.你有一个变量.所有你知道的是它是A类型.你被要求解决对该变量的方法调用.您查看A上可用的插槽,您可以找到匹配的唯一插槽是GetNameSlotA.你不了解GetNameSlotC,因为你只有一个A类型的变量; 你为什么要寻找只适用于C的插槽?
因此,这是对GetNameSlotA中的任何内容的调用.我们已经确定在运行时,GetNameB将位于该槽中.因此,这是对GetNameB的调用.
这里的关键点是,在C#中,重载决策选择一个插槽并生成对该插槽中发生的任何事件的调用.
Bli*_*ndy 24
它应返回"B",因为B.GetName()
它保存在A.GetName()
函数的小虚拟表框中.C.GetName()
是一个编译时"覆盖",它不会覆盖虚拟表,因此您无法通过指针检索它A
.