1.多态介绍
1.1什么是多态
多态指的是一类事物有多种形态,比如动物有多种形态:猫、狗、猪 , 水有水蒸气 , 液体水 , 冰这些形态
多态也是一种编程范式 , 不是说写面向对象的程序必须要有多态
1.2为什么要有多态
就是多态能带来什么样的特性呢?
class Animal:
def say(self):
print('动物的基本发声评率....')
class People(Animal):
def say(self):
super().say()
print('嘤嘤嘤')
class Cat(Animal):
def say(self):
super().say()
print('喵喵喵')
class Pig(Animal):
def say(self):
super().say()
print('哼哼哼')
多态性 : 可以在不考虑对象具体类型的情况下直接使用对象 , 啥意思呢?看代码
obj1 = People()
obj2 = Pig()
obj3 = Cat()
obj1.say()
"""
obj1是人 , 人是动物 , 所以obj1是动物
动物肯定会叫 , 就有say方法
所以我不管你obj1是具体的哪种动物(人,猫,猪)
我可以直接调用say方法
"""
方便了使用者 , 使用者只需要了解统一父类里面有哪些方法 , 然后直接调就可以啦 , 再举一个生活中的例子:
生活中的汽车 , 有奥迪车 , 奔驰车 ,宝马车 , 大众车 , 他们都是汽车
汽车的多态给你带来的好处是什么?
你回想一下你学车时候学的是什么?是奥迪车吗?是奔驰吗?不是 , 是汽车父类中的那些方法 , 等你学会了 , 是不是所有车你都能开(开就是调用方法)
统一了使用标准 , 谁统一的 ? 是父类 , 实际上你一直用多态性 , 只是你不知道 , 在py中一切都是对象 , 你得到的每个数据都是一个对象 , 还记得len方法吗 , 无论是字符串 , 列表 , 元祖都可以使用 , 他们不是不同的类型吗 , 怎么都可以使用len呢? , 看代码
'hello'.__len__()
[1, 2, 3, 4].__len__()
(1, 2, 3, 4, 4, 5,).__len__()
def my_len(obj): # 定义l统一的接口
return obj.__len__()
my_len('hello')
my_len([1, 2, 3, 4])
my_len((1, 2, 3, 4, 4, 5,))
len()就是my_len()方法 , 其中print()也是这样的
1.3多态怎么用
如何在程序中表达出多态呢?
class Animal:
pass
class People(Animal):
pass
class Cat(Animal):
pass
class Pig(Animal):
pass
这不是继承吗? no no no 是多态 , 多态本质上就是在继承背景下衍生的一种概念
2.python推崇的多态-鸭子类型
首先还是看代码 :
class Animal:
def say(self):
print('动物的基本发声评率....')
class People(Animal):
def say(self):
super().say()
print('嘤嘤嘤')
class Cat(Animal):
def say(self):
super().say()
print('喵喵喵')
class Pig(Animal):
def say(self):
super().say()
print('哼哼哼')
我能不能不继承Animal类 , 然后我规范其他几个类都有say方法 , 这样不也是统一了使用标准吗
class People():
def say(self):
print('嘤嘤嘤')
class Cat():
def say(self):
print('喵喵喵')
class Pig():
def say(self):
print('哼哼哼')
当然是可以的 , 这样代码就没有了继承 , 我们知道继承是耦合的一种思想提现 , 但是python觉得我不用继承也能统一使用标准 , 达到一种解耦合的思想 , 啥意思呢 , 就是这三个类 , 在代码上是没有任何关系的 , 只要你们长的像就可以啦 , 这就是python推崇一种类型 , 鸭子类型
鸭子类型就是只要你走路摇摇晃晃 , 嘎嘎叫 , 虽然你不继承
鸭子 , 但是我可以把你认为成就是鸭子 , python推崇的就是这用 , 不是继承父类限制他们 , 而是把他们做的像一点就ok了
补充 :
在linux操作系统中 , 一切皆文件 , 其中也引用了面向对象多态的思想
比如 cpu 内存 都可以读写 , 就类似文件一样 , 这样的设计对开发非常友好 , 所有的开发都变得非常简单
3.补充
使用抽象类的概念来硬性限制子类必须有某些方法名 , 在其他语言中类似接口的概念
import abc# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法 def talk(self): # 抽象方法中无需实现具体的功能 passclass Cat(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准 def talk(self): passcat=Cat() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化