c# - 为什么这个多态的 C# 代码会打印出它的作用?

标签 c# .net oop inheritance polymorphism

我最近获得了以下代码片段作为一种谜题,以帮助理解 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!

现在,在与提出这个谜题的其他开发人员进行了很长时间的交谈之后,我知道输出是什么,但我不会剧透。我真正遇到的唯一问题是我们如何获得该输出、代码如何逐步执行、什么继承了什么,等等。

我认为 C 会被返回,因为它似乎是定义的类。然后我想了想 B 是否会被返回,因为 C 继承了 B - 但 B 也继承了 A(这是我感到困惑的地方!)。


问题:

谁能解释多态性和继承如何在检索输出并最终显示在屏幕上发挥作用?

最佳答案

正确的思考方式是想象每个类都要求它的对象有一定数量的“插槽”;这些插槽充满了方法。问题“实际上调用了什么方法?”需要你弄清楚两件事:

  1. 每个槽的内容是什么?
  2. 调用了哪个插槽?

让我们从考虑插槽开始。有两个插槽。 A 的所有实例都需要有一个槽,我们称之为 GetNameSlotA。 C 的所有实例都需要有一个槽,我们称之为 GetNameSlotC。这就是"new"在 C 中的声明中的含义——它的意思是“我想要一个新插槽”。相对于B中声明的“override”,意思是“我不想要新的slot,我想重新使用GetNameSlotA”。

当然,C继承自A,所以C也一定有槽GetNameSlotA。因此,C 的实例有两个槽——GetNameSlotA 和 GetNameSlotC。不是 C 的 A 或 B 的实例有一个槽,GetNameSlotA。

现在,当您创建一个新的 C 时,这两个插槽中有什么?共有三种方法,我们称之为 GetNameA、GetNameB 和 GetNameC。

A 的声明说“将 GetNameA 放入 GetNameSlotA”。 A 是 C 的父类(super class),因此 A 的规则适用于 C。

B 的声明说“将 GetNameB 放入 GetNameSlotA”。 B 是 C 的父类(super class),因此 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# 中重载决策选择一个插槽,并生成对该插槽中恰好存在的任何内容的调用。

关于c# - 为什么这个多态的 C# 代码会打印出它的作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1508350/

相关文章:

c# - ASP.net c# 母版页问题

c# - 数组写入的性能影响比预期的要大得多

C++ 继承——为什么我的函数没有被使用?

oop - 什么是学习语言的面向对象特性的良好标准练习?

c# - 使用 C# 将 HTML 表格转换为 Excel 工作表

c# - 如何在 C# 中将 PDF Base64 转换为 pdf,然后将 PDF 转换为图像

c# - 是否有现成的 .NET 方法来处理 HttpListener HttpListenerRequest 主体的响应主体?

c# - Net Core : Enforce Required Class Members in Request API Automatically,(非空数据类型)

.net - 使用 Ignore.NotFound 延迟加载 NHibernate

c - 卢阿 :new from C API