继承(下)

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()");

}

}

请看以下使用代码:

时间: 2024-10-07 02:45:43

继承(下)的相关文章

别样JAVA学习(六)继承下(2.1)Object类equals()

上一节继承下(一)我们进行抽象类.接口以及多态的学习, 接下来大家我们讲点特殊的东西就是object类, 我们一直在说继承,子继承了父,父还有没有父类呢, 为什么这么思考,大家想构造函数的第一行是不是都有 一个隐式的super()语句,它们是不是也都会去访问自己的 父类呢?其实是的,这个父类叫什么呢? 叫做Object类,传说JAVA对象中的上帝,哈哈. 1.定义 所有对象的超类,所有对象的直接后者间接父类. 肯定是所有对象都具备的功能. 随便定义一个类 class Demo{}除了隐式的构造方

多重虚继承下的对象内存布局

<深入C++对象模型>绝对是一本值得深读的一本书,书里多次出现一句话,“一切常规遇见虚继承,都将失效”.这是一个有趣的问题,因为C++标准容忍对象布局的实现有较大的自由,出现了各编译器厂商实现的方式不同. 今天谈谈visual studio2013多重虚继承下对象布局.有错不要客气,不要吝啬你的留言,请直接开喷. class y和class z都是从class x虚继承来的子类(也叫派生类),class A是class y和class z的多重继承子类.为了简化问题,下面的data membe

分析多继承下的动态多态。

一.首先我们先了解一下三个概念: 1.重载.2.隐藏.3.覆盖(重写) 如何实现重载?--2个条件: 1-在同一作用域内. 2-两个函数函数名相同,参数不同,返回值可以不同. 此时两个函数就实现了重载,当然这是C++对于C特有的,因为C的时候对参数并没有太多的考虑,C++的编译器在编译时对函数进行了重命名,所以就算是函数名相同的函数,如果参数不同,就会是不同的函数,对应不同的情况. 如何实现隐藏/重定义?--2个条件: 1-在不同作用域下,大多在继承上体现. 2-函数名相同即可. 例如在 B类公

5.2-全栈Java笔记:面向对象的特征(一)继承 | 下

上节我们聊到「Java面向对象的特征:继承」这节我们继续聊一下继承的应用. Object类 Object类基本特性 Object类是所有Java类的根基类,也就意味着所有的JAVA对象都拥有Object类的属性和方法.如果在类的声明中未使用extends关键字指明其父类,则默认继承Object类. [示例1]Object类 public class Person { ... } //等价于: public class Person extends   Object { ... } toStrin

C++ 对象的内存布局—— 虚继承下的虚函数

C++ 对象的内存布局(下)这篇文章的"单一虚拟继承"和"钻石型虚拟继承"时的类内存布局讲得不太清楚,我有一处疑问,我用的是VS2005.因此记录一下. 类继承图例如以下: 这里:类B被类B1和B2虚拟继承,而B1和B2同一时候被D继承. B1的f().B2的f()覆盖了B的f(): D的f()覆盖了B1的f(),D的f1()覆盖了B1的f1() D的f()覆盖了B2的f(),D的f2()覆盖了B2的f2() 类代码例如以下: class B { public: i

虚拟继承下 Virtual Function 的语意

考虑下面的 virtual base class 派生体系: class Point2d { public: Point2d(float = 0.0, float = 0.0); virtual ~Point2d(); virtual void Mumble(); virtual float Z(); //... protected: float _x, _y; }; class Point3d:public virtual Point2d { public: Point3d(float = 0

Django模板继承下的动态数据传递—上下文处理器

参考:http://www.caodahua.cn/detail/3/ 模板继承可以减少页面内容的重复定义,实现页面内容的重用.我的个人博客右侧的导航栏都是继承base页面从而让代码得到最大程度的复用.但是当父模板中有动态数据的话,这些动态数据在子模版中是不会显示的.我们可以通过自定义上下文处理器来解决. Django上下文处理器(Context Processor) 上下文处理器是接收HttpRequest为参数并返回dict形式的数据的函数.它的主要用途是将所有模板共享的公共数据添加到上下文

别样JAVA学习(六)继承下(2.3)异常下

1.RuntimeException Exception中有一个特殊的子类异常RuntimeException执行时异常. 假设在函数内容抛出该异常,函数上能够不用声明.编译一样通过. 假设在函数上声明了该异常,调用者能够不用进行处理.编译一样通过. 之所以不用在函数上声明,是由于不须要让调用者处理. 当该异常发生,希望程序停止. 由于在执行时,出现了无法继续运算的情况, 希望停止程序后.对代码进行修正. 例: class Person { public void checkName(Strin

JAVA学习第十三课(继承下:抽象类abstract)

抽象:模糊 == 看不懂 继承:发现事物之间的共性关系,并向上抽取,以提高代码的复用性 事物里都具备这个功能,但是这个功能是什么,怎么去做,不知道,这就涉及到了抽象 1.继承:A,B两个类,都有show的功能,实现方式也一样那么就可以向上抽取其共性,做新类,使A,B继承于新类. 2.抽象:A,B两个类,都有show的功能,但是功能的实现方式不一样,那么向上抽取其方法生明,但是内容不一样,那么就用关键字abstract标识,表示抽象函数,那么这个类也必须用abstract标识,表示抽象类 abst

别样JAVA学习(六)继承下(2.2)Object类toString()

接下来说完equals以后,我们学习接下来的toString(), Java又认为所有对象不光具有比较性, 还能使对象变成字符串被打印. 出现 以前前面显示的是数组,现在显示的是这个对象所属的类, 紧跟着是这个对象的哈希值,也就是所有的对象都有哈希值(内存地址). 接下来,修改ObjectDemoToString class类 class ObjectDemoToString { public static void main(String[] args) { Demo d1=new Demo(