19. 面向对象之多态、鸭子类型、抽象类

多态

多态:指的是同一种事物的多种形态,指的是可以在不考虑对象具体类型的情况下而直接使用对象

​ 多态性指的是可以在不用考虑对象具体类型的情况下而直接使用对象,这就需要在设计时,把对象的使用方法统一成一种:例如cat、dog、pig都是动物,但凡是动物肯定有talk方法,于是我们可以不用考虑它们三者的具体是什么类型的动物,而直接使用cat.talk()、dog.talk()、pig.talk()等等

# 为何要有多态=》多态会带来什么样的特性,多态性   
class Animal:  # 统一所有子类的方法
    def say(self):
        print('动物基本的发声频率。。。',end=' ')
class People(Animal):
    def say(self):
        super().say()
        print('嘤嘤嘤嘤嘤嘤嘤')
class Dog(Animal):
    def say(self):
        super().say()
        print('汪汪汪')
class Pig(Animal):
    def say(self):
        super().say()
        print('哼哼哼')
obj1=People()
obj2=Dog()
obj3=Pig()
obj1.say()  # 直接使用功能,不用分辨对象是什么
obj2.say()
obj3.say()

# 进一步定义统一的接口,接收传入的动物对象,这样就可以直接使用了
# 这个有点像python中的len()这种方法,就是直接将对象传入,然后就能将对象的长度计算出来,不需要管传入的对象的种类是什么
def animal_say(animal):
    animal.say()
animal_say(obj1)
animal_say(obj2)
animal_say(obj3)

​ 多态性的本质在于不同的类中定义有相同的方法名,这样我们就可以不考虑类而统一用一种方式去使用对象,可以通过在父类引入抽象类的概念来硬性限制子类必须有某些方法名

抽象类与限制子类必须有某种方法

import abc
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod  # 该装饰器限制子类必须定义有一个名为talk的方法
    def talk(self):  # 抽象方法中无需实现具体的功能,可以单纯的只是一种限制
        pass

class Cat(Animal): # 但凡继承Animal的子类都必须有talk方法,但是内容无限制,可以不同
    def talk(self):
        pass
cat=Cat()  # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化

其他的方法进行子类实现某种方法:

提取⽗类. 然后在⽗类中定义好⽅法. 在这个⽅法中什么都不⽤⼲. 就抛⼀个异常就可以了. 这样所有的⼦类都必须重写这个⽅法. 否则. 访问的时候就会报错

class Payment:
    """
    此类什么都不做,就是制定一个标准,谁继承我,必须定义我里面的方法。
    """
    def pay(self,money):
        raise Exception("你没有实现pay方法")

class QQpay(Payment):
    def pay(self,money):
        print('使用qq支付%s元' % money)

class Alipay(Payment):
    def pay(self,money):
        print('使用阿里支付%s元' % money)

class Wechatpay(Payment):
    def fuqian(self,money):
        print('使用微信支付%s元' % money)


def pay(obj,money):
    obj.pay(money)

a = Alipay()
b = QQpay()
c = Wechatpay()
pay(a,100)
pay(b,200)
pay(c,300)

当然了,推荐抽象类的用法

鸭子类型

​ 上面的多态的实现是基于继承实现的,但是实际上我们完全可以不依赖于继承,只需要制造出外观和行为相同对象,同样可以实现不考虑对象类型而使用对象,这正是Python崇尚的“鸭子类型”(duck typing):“如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子”。比起继承的方式,鸭子类型在某种程度上实现了程序的松耦合度

# 二者看起来都像文件,因而就可以当文件一样去用,然而它们并没有直接的关系
class Txt:   # Txt类有两个与文件类型同名的方法,即read和write
    def read(self):
        pass
    def write(self):
        pass

class Disk:   # Disk类也有两个与文件类型同名的方法:read和write
    def read(self):
        pass
    def write(self):
        pass
上一篇:objective-c 之类的声明与调用(2021-11-10)


下一篇:ES6-字符串扩展