《程序员小瑞的蜜月计划》,揭示面向对象(C++为例)中多态的真实原理和应用领域

        很多同学无法理解多态是怎么回事。什么叫:同样的消息作用在不同的对象上给出不同的反应?

        其实现实中,多态的例子是有很多的,比如:挪动的指令,如果传递给一辆车的话,那就是挪车,实际的动作就是把车开走。如果传递给一个凳子的话,那就是挪凳子,实际的动作应该是把凳子拎走。这就是多态。

        那么,在面向对象程序设计里,多态又有什么用呢?

        总结一句话就是:

     多态,为了增加程序的可扩展性。

        接下来,我们用一个小例子给大家解释一下多态的真实原理和应用领域。

        程序员小瑞刚结婚,正在筹备马尔代夫蜜月计划,酒店刚订完,Leader来电话,儿童益智游戏《小马良》项目批下来了。收益丰厚。项目完成需两个月。     

        主要功能:教孩子画画。可显示多种图形,甚至可以求图形面积和周长。   

        技术路线:面向对象技术。已有基类Point,后续各种形状子类有待进一步设计。形状数量未知。

        小瑞的任务:设计开发一个函数,用来显示图形。

        眼看马代计划泡汤。小瑞怎么办?

        三套方案:

        1.世界那么大,我出去走走。自己是爽了,工作丢啦。

        2. 开启敬业模式,持续更新代码,等待后续的图形子类一一设计完成,针对性的订制显示图形的函数。 倒不是不可以,只是蜜月肯定是泡汤了,因为不知道到底有多少图形子类被设计出来,周期未知。

        3.开发一个通用函数,无论后续有多少图形子类设计出来,都能够兼容的完成显示图形的功能。 小瑞开心:可以提前做好放在那,提着行李箱带着老婆去蜜。 老板高兴:等他蜜月回来,可以给安排别的任务,能者多劳。

        问题就变成了,如何开发一个通用函数,能适应所有类别的图形的绘制?

        要解决这个问题,需要一个面向对象语言支持以下几个机制:

        1.类型适应

        类型适应是在继承关系中,子类对象和基类对象的微妙关系。简单来说,有下面三种形式(主要关注形式1和2)

        形式1:子类对象可以作为基类对象来使用。

                一个研究生可以作为一个学生来使用。

                 一只猫可以作为一个动物来使用。

                Point p; Circle c;其中Circle是Point的子类。

                p = c; 合法。

                语义上:c是一种Point,所以,c可以当做Point来使用。

                语法上:c继承了Point类的属性,它有满足向p赋值的所有数据。

        形式2:基类指针可以指向子类对象。

                Point *p; Circle c;其中Circle是Point的子类。

                p = &c; 合法。

                语义上:c是一种Point,所以,p可以指向c。

                语法上:c继承了Point类的属性,通过Point类指针p可以指向c中所有基类成员。

                

        形式3:基类的引用可以引用子类对象。(C++)

                 Circle c;其中Circle是Point的子类。

                Point &p = c; 合法。

                语义上:c是一种Point,所以,c可以当做Point来使用

                语法上:c继承了Point类的属性,通过Point类引用p可以引用到c中所有基类成员。

                

        2.函数覆盖(override)

         基类与子类中存在具有完全相同的函数原型的函数,称为子类对基类的函数覆盖。

        考虑一下,《小马良》项目中Point类和Circle类设计。Point是基类,Circle是子类。

        

         display就是一个典型的函数覆盖,也叫重写函数。

        小试牛刀:

        结合类型适应机制和函数覆盖机制,以上图设计的Point类和Circle类为基础,尝试设计一个通用的函数Disp,用来显示图形。

        

         注意:Disp的参数为一个基类Point的引用。根据类型适应原则第三条,main函数中的子类Circle的对象c可以被基类引用p来引用。而根据函数覆盖原则,Circle类和Point类都定义了一个一模一样函数原型的函数display,当然函数定义的内容肯定不同,Circle类的display肯定是显示圆信息用的,Point的display则是显示点信息用的。在本例中,Disp函数的形式参数是Point引用p,实际参数是Circle对象c,p.display()这条语句则应该调用Circle类的display函数,显示一个圆。

        如果是Python或者Java这种纯面向对象语言。多态的实现,就可以到此为止了。通用函数Disp也就开发完毕了。以后再出现任何新的基于Point的图形子类,如rectangle,triangle,square等,只要这些子类实现对display的函数覆盖,都可以调用Disp函数,实现相应图形对象的显示。

也就是说:上图中的Disp不需要任何改动,真正实现了零维护

马尔代夫不是梦。

        但是C++作为过渡时期的产物,支持多态的能力较弱,还需要手动的进行一个设置。我们叫他,虚函数。

只需要在函数定义前加上关键字virtual就可以啦。至于背后的机理,就不在这里阐述了。 

学会了就点个赞吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎风工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值