• 继承(下)


    4.4方法重载、隐藏与虚方法调用

          由于子类对象同时汇集了父类和子类的所有公共方法,而 C#并未对子类和父类的

    方法名称进行过多限制,因此,一个问题出现了:

          如果子类中某个方法与父类方法的签名一样(即方法名和方法参数都一样),那当通过

    子类对象访问此方法时,访问的是子类还是父类所定义的方法?

          让我们先从子类方法与父类方法之间的关系说起。

          总的来说,子类方法与父类方法之间的关系可以概括为以下三种。

    • 扩充(Extend):子类方法,父类没有;
    • 重载(Overload):子类有父类的同名函数,但参数类型或数目不一样;
    • 完全相同:子类方法与父类方法从方法名称到参数类型完全一样。

          对于第一种扩充关系,由于子类与父类方法不同名,所以不存在同名方法调用的问

    题,重点分析一下后两种情况.

    (1)重载(overload)

          在前面介绍过方法重载的概念,在同一个类中构成重载的方法主要根据参数列表来决定

    调用哪一个。这一基本判断方法可以推广到类的继承情况。

          例如,以下代码在子类和父类中定义了一个重载的方法 OverloadF():

     

    (2)隐藏(Hide)

          当子类与父类拥有完全一样的方法时,称子类隐藏了父类的同名方法,请看示例项目 HideExamples:

     

     

         请注意现在子类和父类都拥有了一个完全相同的方法 HideF(),于是问题发生了,请看

    以下代码:

          Child c = new  Child();

          c.HideF();//调用父类的还是子类的同名方法?

    Child c = new  Child();

    Parent  p;

    p = c;

    p.HideF(); //调用父类的还是子类的同名方法?

     

         上述代码的运行结果是:

     

          Parent.HideF()

     

          这就意味着即使 Parent变量  p中实际引用的是  Child类型的对象,通过  p调用的方法还

     

    是 Parent类的!

     

          如果确实希望调用的子类的方法,应这样使用:

     

          ((Child)p).HideF();

     

          即先进行强制类型转换。

     

          回到前面 Parent和  Child类的定义,Visual  Studio在编译这两个类时,会发出一个警告:

     

          警告1“HideExamples.Child.HideF()”隐藏了继承的成员

     

          “HideExamples.Parent.HideF()”。如果是有意隐藏,请使用关键字 new。

     

          虽然上述警告并不影响程序运行结果,却告诉我们代码不符合     C#的语法规范,修改

     

    Child类的定义如下:

     

          class Child :  Parent

     

         {

     

               public new void HideF()

     

            {

     

                 System.Console.WriteLine("Child.HideF()");

     

             }

     

         }

     

          “new”关键字明确告诉 C#编译器,子类隐藏父类的同名方法,提供自己的新版本。

     

          由于子类隐藏了父类的同名方法,所以如果要在子类方法的实现代码中调用父类被隐藏

     

    的同名方法,请使用 base关键字,示例代码如下:

     

    base.HideF(); //调用父类被隐藏的方法

     

    (3)重写(override)与虚方法调用

     

          上述隐藏的示例中,由于子类隐藏了父类的同名方法,如果不进行强制转换,就无法通

     

    过父类变量直接调用子类的同名方法,哪怕父类变量引用的是子类对象。

     

          这是不太合理的。我们希望每个对象都只干自己职责之内的事,即如果父类变量引用

     

    的是子类对象,则调用的就是子类定义的方法,而如果父类变量引用的就是父类对象,则调

     

    用的是父类定义的方法。这就是说,希望每个对象都各人自扫门前雪,莫管他人瓦上霜

     

          为达到这个目的,可以在父类同名方法前加关键字 virtual,表明这是一个虚方法,子类

     

    可以重写此方法:即在子类同名方法前加关键字 override,表明对父类同名方法进行了重写。

     

          请看示例代码(示例项目 VirtualExamples):

          class  Parent

        {

              public  virtual void OverrideF()

            {

                   System.Console.WriteLine("Parent.OverrideF()");

             }

         }

          class Child :  Parent

        {

                public  override void OverrideF()

           {

                   System.Console.WriteLine("Child.OverrideF()");

            }

         }

          请看以下使用代码:

  • 相关阅读:
    GRE协议基础配置
    OSPFv3基础配置
    初级作业2
    缺省静态路由发布进OSPF
    不同进程OSPF路由相互通信
    OSI与TCP/IP
    华为AAA认证详解
    OSPF与静态路由
    [转]那些著名或非著名的iOS面试题(下)
    [转]那些著名或非著名的iOS面试题(中)
  • 原文地址:https://www.cnblogs.com/LCL390/p/4300807.html
Copyright © 2020-2023  润新知