遥不可及|C#中子类对基类方法的继承、重写和隐藏( 二 )


子类隐藏基类的虚方法考虑下面的代码
class Person{public virtual void Greeting(){Console.WriteLine("Hello, I am Person");}}class Employee : Person{public new virtual void Greeting(){Console.WriteLine("Hello, I am Employee");}}class Manager : Employee{public override void Greeting(){Console.WriteLine("Hello, I am Manager");}}class Program{static void Main(string[] args){Manager m = new Manager();Person p = m;Employee e = m;p.Greeting();e.Greeting();m.Greeting();}}猜一下输出应该是什么?这也是老胡曾经遇到过的一道笔试题 , 表面看着简单 , 但是不注意也会掉坑里
1 , 2 , 3 , 答案揭晓
遥不可及|C#中子类对基类方法的继承、重写和隐藏是不是有点出乎意料呢 , 让我们来分析一下
遥不可及|C#中子类对基类方法的继承、重写和隐藏首先 , 三次调用均是callvirt , 而且方法 Greeting 是虚方法 , 我们需要考虑对象实例以决定要调用的方法 。

  • 在第一次调用中 , 引用变量类型是Person , 虽然对象实例类型Manger重写了Greeting方法 , 但是它重写的是继承自Manger基类Emplyee的Greeting方法 , Person中Greeting方法在子类Manger中仅仅是被隐藏而没有被重写 , 所以这里调用的是Person中的Greeting
  • 而第二次调用中 , 引用变量类型是Employee , Employee的Greeting方法被Manager重写 , 所以这次调用到的是Manager中的Greeting
  • 最后一次调用毋庸多言 , 简单的重写案例而已
怎么样 , 是不是有小伙伴猜错结果了?
总结在子类对基类有方法继承、重写和隐藏的情况下 , 有时候判断具体哪个方法被调用会有难度 , 但请记住以下要点:
  • 如果被调用方法非虚 , 那么只用关注引用变量类型就好 , 引用变量类型能决定调用方法在哪里
  • 如果调用方法为虚 , 我们需要站在引用变量类型的角度 , 审视该方法是否被对象类型所重写;若是 , 则调用对象类型的重写方法;反之 , 则再次让引用变量类型决定调用方法 。
这样 , 当我们再遇到子类隐藏基类虚方法的情况 , 应用以上要点就可以拨云见日 。
原文作者:老胡写代码
原文地址:


推荐阅读