面相对象之多态和鸭子类型

面相对象之多态和鸭子类型

  • 多态指的是一类事物有多种形态

一、多态动态绑定(多态性)

  • 多态动态绑定在继承的背景下使用时,有时也称为多态性

  • 多态性是指在不考虑实例类型的情况下使用实例

  • 在面向对象方法中一般是这样表述多态性:

    • 向不同的对象发送同一条消息
    • 不同的对象在接收时会产生不同的行为(即方法)
    • 也就是说,每个对象可以用自己的方式去响应共同的消息
    • 所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数
  • 举个例子就是:应对同一个事件下雨了

    • 卖雨伞的商家会觉得高兴可以把伞卖出去了
    • 卖防晒霜的商家就难过防晒霜卖不出了
  • 不同的商家对于同一件事情的不同反应和状态就可以类比成不同的子类对于父类方法的不同表现

class Animal(object):
    def speak(self):
        ...

# 不同的子类对于父类的同一个方法的实现是不同的
class Person(Animal):
    def speak(self):
        print('哎呦~你干嘛~')


class Duck(Animal):
    def speak(self):
        print('嘎嘎嘎!')


class Dog(Animal):
    def speak(self):
        print('汪汪汪!')


people = Person()
duck = Duck()
dog = Dog()
people.speak()  # 哎呦~你干嘛~
duck.speak()  # 嘎嘎嘎!
dog.speak()  # 汪汪汪!

二、多态性的分类

  • 多态性分为静态多态性和动态多态性

[1]静态多态性

  • 如任何类型都可以用运算符 + 进行运算

[2]动态多态性

import abc


class Animal(object):
    @abc.abstractmethod
    def speak(self):
        ...


class Person(Animal):
    def speak(self):
        print('哎呦~你干嘛~')


class Duck(Animal):
    def speak(self):
        print('嘎嘎嘎!')


class Dog(Animal):
    def speak(self):
        print('汪汪汪!')


def func(obj):
    obj.speak()


people = Person()
duck = Duck()
dog = Dog()

func(people)  # 哎呦~你干嘛~
func(duck)  # 嘎嘎嘎!
func(dog)  # 汪汪汪!
  • Python中一切皆对象,本身就支持多态性
name = 'Xanadu'
my_list = [1, 2, 3]
my_dict = {'name': 'Xanadu', 'age': 18}

print(len(name))  # 6
print(len(my_list))  # 3
print(len(my_dict))  # 2

三、多态性的好处

  • 增加了程序的灵活性
    • 以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)
  • 增加了程序额可扩展性
    • 通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用
import abc


class Animal(object, metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def speak(self):
        ...


# 如果我们要新增一个动物类的子类:猫类
class Cat(Animal):
    # 不需要改变什么直接使用原来的方式定义猫类
    def speak(self):
        print('喵喵喵!')


def func(obj):
    obj.speak()


cat = Cat()
# 调用speak的方式也不会改变
func(cat)  # 喵喵喵!

四、鸭子类型duck-typing

  • 鸭子类型是一种编程风格,决定一个对象是否有正确的接口
    • 关注点在于它的方法或属性,这个鸭子也可以是鸡是狗
    • 而不是它的类型(如果它看起来像鸭子,像鸭子一样嘎嘎叫,那么它一定是鸭子。)。
  • 通过强调接口而不是特定类型,设计良好的代码通过多态提高了灵活性。
    • 鸭子类型无需使用 type()isinstance() 进行检查(注意,鸭子类型可以用抽象基类来补充)
    • 相反,它通常使用 hasattr() 来检查,或是 EAFP 编程。
# 狗和哈士奇都会汪汪叫都会跑,所以都可以都是狗
class Dog(object):
    def speak(self):
        print('狗会汪汪叫。')

    def run(self):
        print('狗会跑。')

class Huskies(object):
    def speak(self):
        print('哈士奇会汪汪叫。')

    def run(self):
        print('哈士奇会跑。')
posted @ 2024-01-29 14:44  桃源氏  阅读(21)  评论(0)    收藏  举报