博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
类的多态
阅读量:6070 次
发布时间:2019-06-20

本文共 5210 字,大约阅读时间需要 17 分钟。

#我们前面了解了继承,继承可以帮助我们重复使用代码。但对于继承中的示例,无论是Dog还是Cat,调用父类的run()方法时显示的都是Animal is running.,如果想让结果显示为Dog is running.和Cat is running.,该如果处理呢?
#我们对Dog和Cat做如下改进:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #clas_多态 4  5 class Animal(object): 6     def run(self): 7         print('Animal is running.') 8  9 class Dog(Animal):10     def run(self):11         print('Dog is running.')12 13 class Cat(Animal):14     def run(self):15         print('Cat is running.')
#执行如下语句:
1 dog=Dog()2 print('实例化Dog类')3 dog.run()4 5 cat=Cat()6 print('实例化Cat类')7 cat.run()
#程序执行结果如下:
1 D:\Python\workspace\datatime\20171129>python class_多态.py2 实例化Dog类3 Dog is running.4 实例化Cat类5 Cat is running.
#由执行结果看到,分别得到了Dog和Cat各自的running结果。
#当子类和父类存在相同的run()方法时,子类的run()方法会覆盖父类的run()方法,在代码运行时总会调用子类的run()方法,称之为多态。
#多态来自于希腊语,意思是有多种形式。多态意味着即使不知道变量所引用的对象类型是什么,也能对对象进行操作,多态会根据对象(或类)的不同而表现出不同的行为。例如,我们在上面的Animal类中定义了run方法,Dog和Cat分别继承Animal类,并且分别定义了自己的run方法,最后Dog和Cat调用的还是自己定义的run方法。
#为了更好了解什么是多态,我们对数据类型再做一个说明。当我们定义一个类时,实际上就是定义了一种数据类型。定义的数据类型和Python自带的数据类型(如str、list、dict)没什么区别。
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #clas_多态 4  5 class Animal(object): 6     def run(self): 7         print('Animal is running.') 8  9 class Dog(Animal):10     pass11 12 a=list()           #a是list类型13 b=Animal()         #b是Animal类型14 c=Dog()            #c是Dog类型
#下面用isinstance()方法判断一个变量是否是某个类型。
1 print('a是否是list类型:',isinstance(a,list))2 print('b是否是Animal类型:',isinstance(b,Animal))3 print('c是否是Dog类型:',isinstance(c,Dog))
#执行结果如下:
1 D:\Python\workspace\datatime\20171129>python class_多态.py2 a是否是list类型: True3 b是否是Animal类型: True4 c是否是Dog类型: True
#由执行结果看到,a,b,c确实分别为list、Animal、Dog三种类型。我们再执行如下语句:
1 print('c是否是Dog类型:',isinstance(c,Dog))2 print('c是否是Animal类型:',isinstance(c,Animal))
#执行结果如下:
1 c是否是Dog类型: True2 c是否是Animal类型: True
#由执行结果看到,c既是Dog类型又是Animal类型,这怎么理解呢?
#因为Dog是从Animal继承下来的,当我们创建Dog的实例c时,我们认为c的数据类型是Dog,但c同时也是Animal,Dog本来就是Animal的一种。
#在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以看作是父类。但反过来就不行,例如如下语句:
1 print('b是否是Dog类型:',isinstance(b,Dog))
#执行结果如下:
1 b是否是Dog类型: False
#由输出结果看到,变量b是Animal的实例化对象,是Animal类型,但不是Dog类型,也就是Dog可以看成Animal,但Animal不可以看成Dog。
#我们再看一个示例。编写一个函数,这个函数接收一个Animal类型的变量,定义并执行如下函数,执行时传入Animal的实例:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #class_多态_2 4  5 class Animal(object): 6     def run(self): 7         print('Animal is running.') 8  9 def run_two_times(animal):10         animal.run()11         animal.run()12 13 run_two_times(Animal())
#执行结果如下:
1 D:\Python\workspace\datatime\20171129>python class_多态_2.py2 Animal is running.3 Animal is running.
#若执行函数传入Dog的实例,操作如下:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #class_多态_2 4  5 class Animal(object): 6     def run(self): 7         print('Animal is running.') 8  9 class Dog(Animal):10     def run(slef):11         print('Dog is running.')12 13 def run_two_times(animal):14         animal.run()15         animal.run()16 17 run_two_times(Dog())
#得到的执行结果如下:
1 D:\Python\workspace\datatime\20171129>python class_多态_2.py2 Dog is running.3 Dog is running.
#若传入Cat的实例,操作如下:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #class_多态_2 4  5 class Animal(object): 6     def run(self): 7         print('Animal is running.') 8  9 class Dog(Animal):10     def run(slef):11         print('Dog is running.')12 13 class Cat(Animal):14     def run(self):15         print('Cat is running.')16 17 def run_two_times(animal):18         animal.run()19         animal.run()20 21 run_two_times(Animal())22 run_two_times(Dog())23 run_two_times(Cat())
#得到执行结果如下:
1 D:\Python\workspace\datatime\20171129>python class_多态_2.py2 Animal is running.3 Animal is running.4 Dog is running.5 Dog is running.6 Cat is running.7 Cat is running.
#看上去没有什么特殊的地方,已经正确输出预期结果了,但仔细想想看,如果再定义一个Bird类型,也继承Animal类,定义如下:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #class_多态_2 4  5 class Animal(object): 6     def run(self): 7         print('Animal is running.') 8  9 class Dog(Animal):10     def run(slef):11         print('Dog is running.')12 13 class Cat(Animal):14     def run(self):15         print('Cat is running.')16 17 class Bird(Animal):18     def run(self):19         print('Bird if flying the sky.')20 21 def run_two_times(animal):22         animal.run()23         animal.run()24 25 run_two_times(Animal())26 run_two_times(Dog())27 run_two_times(Cat())28 run_two_times(Bird())
#程序执行结果如下:
1 D:\Python\workspace\datatime\20171129>python class_多态_2.py2 Animal is running.3 Animal is running.4 Dog is running.5 Dog is running.6 Cat is running.7 Cat is running.8 Bird if flying the sky.9 Bird if flying the sky.
#由执行结果看到,新增的Animal子类不必对run_two_times()方法做任何修改。实际上,任何依赖Animal作为参数的函数或方法都可以不加修改地正常运行,原因就在于多态。
#多态的好处是:当我们需要传入Dog、Cat、Bird等对象时,只需要接收Animal类型就可以了,因为Dog、Cat、Bird等都是Animal类型,按照Animal类型进行操作即可。由于Animal类型有run()方法,因此传入的类型只要是Animal类或继承自Animal类,都会自动调用实际类型的run()方法。
#多态的意思是:对于一个变量,我们只需要知道它是Animal类型,无需确切知道它的子类型,就可以放心调用run()方法。具体调用的run()方法作用于Anial、Dog、Cat或Bird对象,由运行该对象的确切类型决定。
#多态真正的威力在于:调用方只管调用,不管细节。当我们新增一种Animal的子类时,只要确保run()方法编写正确即可,不用管原来的代码如何调用的,这就是著名的“开闭”原则:对于扩展开放,允许新增Animal子类;对于修改封闭,不需要修改依赖Animal类型的run_two_times()等函数。
#很多函数和运算符都是多态的,也许你写的程序也可能时,即使你并非有意这样的。只要使用多态函数和运算符,多态就会消除。唯一能够毁掉多态的是使用函数显式地检查类型,如type、isinstance函数等,如果有可能,就尽量避免使用这些会毁掉多态的方式,重要的是如何让对象按照我们希望的方式工作,无论它是否是正确类型或类。

转载于:https://www.cnblogs.com/DLHe/p/7927394.html

你可能感兴趣的文章
[Linux内核]ctrl-z/fg/bg/nohup/setsid/()与&/disown/screen
查看>>
VS没办法调试,直接退出,报错:1. 使用调试生成配置或禁用调试选项“启用‘仅我的代码’”。。。...
查看>>
C# 委托应用总结
查看>>
Linux驱动技术(七) _内核定时器与延迟工作
查看>>
裁判文书网采集说明
查看>>
Reverse Engineering Custom DataTypes -> GUID() in SQL Server to PostgreSQL
查看>>
配置Tomcat apr运行模式
查看>>
BZOJ3490 : Pa2011 Laser Pool
查看>>
windows 10 超级优化提速 附系统服务列表纯净
查看>>
【jmeter】 jmeter 测试HTTP接口
查看>>
求幂,我居然又没做出来
查看>>
openssh安装/更新教程(CentOS)
查看>>
QTcpSocket 发送和接收数据的几种方法
查看>>
springboot-5-整合jpa
查看>>
40个新鲜的 jQuery 插件,使您的网站用户友好
查看>>
Android Studio设置图片背景及主题设置
查看>>
mysql function动态执行不同sql语句
查看>>
maven docker plugin 常见问题解决
查看>>
linux下查看各硬件型号
查看>>
仿<赶集生活>client启动动画效果
查看>>