1.多态
python面向对象三大特征:封装、继承和多态。
多态(polymorphism)是指同一个方法调用由于对象不同可能会产生不同的行为; 在现实生活中, 我们有很多例子;
比如: 同样是调用人的休息方法, 张三的休息是睡觉, 李四的休息是玩游戏, 王五的休息是逛街;
同样是吃饭的方法, 中国人用筷子吃饭, 英国人用刀叉吃饭, 印度人用手吃饭;
在我们python的面向对象里就是不同的对象在接收相同方法或者函数时会产生不同的行为,
也就是说,每个对象可以用自己的方式去响应共同的函数,不同的方式实现不同的结果。
关于多态 要注意以下两点
1.多态是方法的多态,属性没有多态
2.多态的存在有两个2个必要条件:继承,方法重写
//# 多态
# 多态(polymorphism)是指同一个方法调用由于对象不同可能会产生不同的行为; 在现实生活中, 我们有很多例子;
# 比如: 同样是调用人的休息方法, 张三的休息是睡觉, 李四的休息是玩游戏, 王五的休息是逛街;
# 同样是吃饭的方法, 中国人用筷子吃饭, 英国人用刀叉吃饭, 印度人用手吃饭;
#
# 在我们python的面向对象里就是不同的对象在接收相同方法或者函数时会产生不同的行为,
# 也就是说,每个对象可以用自己的方式去响应共同的函数,不同的方式实现不同的结果。
#
# 关于多态 要注意以下两点
# 1.多态是方法的多态,属性没有多态
# 2.多态的存在有两个2个必要条件:继承,方法重写
class Animals:
def shout(self):
print('Animals叫了一声,我是父类')
class Dog(Animals):
def shout(self): #只有继承和重写父类方法,才能有多态,不然都是一样的,不存在多态
print('小狗汪汪汪')
class Pig(Animals):
def shout(self):
print('小猪昂昂昂')
D=Dog()
D.shout()
S=Pig()
S.shout() #多态:一个方法名调用,根据对象的不同,调用不同的方法
# 他们方法名虽然一样,但是内容不一样且对象不一样,故每个对象调用的同名方法都是不一样的
print('-------------------------------------')
# python3
# 抽象基类
# abc.abstractmethod
# 有时,我们抽象出一个基类,知道要有哪些方法,但只是抽象方法,并不实现功能,只能继承,
# 而不能被实例化,但子类必须要实现该方法。看下面的例子:
import abc
class Foo(abc.ABC):
@abc.abstractmethod
def fun(self):
pass
# a = Foo() #会报错
# 实例化报错
# TypeError: Can't instantiate abstract class Foo with abstract methods fun
#案例2
#在我们python的面向对象里就是不同的对象在接收相同方法或者函数时会产生不同的行为,
#也就是说,每个对象可以用自己的方式去响应共同的函数,不同的方式实现不同的结果。
import abc
class Animal(metaclass=abc.ABCMeta): # 同一类事物:动物
@abc.abstractmethod # 上述代码子类是约定俗称的实现这个方法,加上@abc.abstractmethod装饰器后严格控制子类必须实现这个方法 如果子类没有实现这个方法,就会报错并停止执行代码
def talk(self):
pass #@abc.abstractmethod装饰器 是为了提醒程序员是否创建了这个方法,如果加上该装饰器,程序员在编写子类时忘了定义这个方法时,会报错
class People(Animal): # 动物的形态之一:人
def talk(self):
print('say hello')
class Dog(Animal): # 动物的形态之二:狗
def talk(self):
print('say wangwang')
class Pig(Animal): # 动物的形态之三:猪
def talk(self):
print('say aoao')
def func(obj):
obj.talk()
func1=Pig() #调用接口
func(func1) #结果为say aoao
peo2 = People()
pig2 = Pig()
d2 = Dog()
peo2.talk()
pig2.talk()
d2.talk()
print('--------------------------------')
#文件有多种形态:文本文件,可执行文件
import abc
class File(metaclass=abc.ABCMeta): # 同一类事物:文件
@abc.abstractmethod
def click(self):
pass
class Text(File): # 文件的形态之一:文本文件
# def click(self):
# print('open file')
pass #因为该子类未定义被(metaclass=abc.ABCMeta) ,装饰器@abc.abstractmethod修饰的方法,所以报错
class ExeFile(File): # 文件的形态之二:可执行文件
def click(self):
print('execute file')
file=Text()
file.click()
file2=ExeFile()
file2.click()
结果为
小狗汪汪汪
小猪昂昂昂
-------------------------------------
say aoao
say hello
say aoao
say wangwang
--------------------------------
Traceback (most recent call last):
File "C:/Users/HP/PycharmProjects/py大师之面向对象2/多态2.py", line 94, in <module>
file=Text()
TypeError: Can't instantiate abstract class Text with abstract methods click
2.多态性:
一 什么是多态动态绑定(在继承的背景下使用时,有时也称为多态性)
多态性是指在不考虑实例类型的情况下使用实例
在面向对象方法中一般是这样表述多态性:
向不同的对象发送同一条消息(!!!obj.func():是调用了obj的方法func,又称为向obj发送了一条消息func),不同的对象在接收时会产生不同的行为(即方法)。
也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
// 比如:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生执行的是放学操作,虽然二者消息一样,但是执行的效果不同
//
peo=People()
dog=Dog()
pig=Pig()
#peo、dog、pig都是动物,只要是动物肯定有talk方法
#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
peo.talk()
dog.talk()
pig.talk()
#更进一步,我们可以定义一个统一的接口来使用
def func(obj):
obj.talk()
3.抽象基类
有时,我们抽象出一个基类,知道要有哪些方法,但只是抽象方法,并不实现功能,只能继承,而不能被实例化,但子类必须要实现该方法,这就需要用到抽象基类,在很多时候用到的很多
python3
抽象基类
@ abc.abstractmethod
有时,我们抽象出一个基类,知道要有哪些方法,但只是抽象方法,并不实现功能,只能继承,
而不能被实例化,但子类必须要实现该方法。看下面的例子:
// import abc
class File(metaclass=abc.ABCMeta): # 同一类事物:文件
@abc.abstractmethod
def click(self):
pass
class Text(File): # 文件的形态之一:文本文件
# def click(self):
# print('open file')
pass #因为该子类未定义被(metaclass=abc.ABCMeta) ,装饰器@abc.abstractmethod修饰的方法,所以报错
class ExeFile(File): # 文件的形态之二:可执行文件
def click(self):
print('execute file')
file=Text()
file.click()
file2=ExeFile()
file2.click()
结果为:
Traceback (most recent call last):
File "C:/Users/HP/PycharmProjects/py大师之面向对象2/多态2.py", line 94, in <module>
file=Text()
TypeError: Can't instantiate abstract class Text with abstract methods click