首页 > 其他分享 >面相对象之多态和鸭子类型

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

时间:2024-01-29 14:57:51浏览次数:37  
标签:多态性 self 多态 鸭子 print 面相 class def speak

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

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

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

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

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

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

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

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

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('哈士奇会跑。')

标签:多态性,self,多态,鸭子,print,面相,class,def,speak
From: https://www.cnblogs.com/taoyuanshi/p/17994492

相关文章

  • C# 继承、多态性、抽象和接口详解:从入门到精通
    C#继承在C#中,可以将字段和方法从一个类继承到另一个类。我们将“继承概念”分为两类:派生类(子类)-从另一个类继承的类基类(父类)-被继承的类要从一个类继承,使用:符号。在以下示例中,Car类(子类)继承了Vehicle类(父类)的字段和方法:示例classVehicle//基类(父类){......
  • 一篇文章带你搞懂Python中的继承和多态
    在面向对象编程中,继承和多态是两个核心概念。它们是面向对象编程的基石,允许我们构建更加复杂和可重用的代码。本文将通过理论与实践相结合的方式,深入探讨Python中的继承和多态,帮助你更好地理解这两个概念。一、继承1、什么是继承?继承是面向对象编程中的一个重要概念,它允许我们创建......
  • 32多态
    多态静态(编译时期)的多态:函数重载(在编译阶段就确定好调用的函数版本)、模板(函数模板和类模板)动态(运行时期)的多态:在继承结构中,基类指针(引用)指向派生类对象,通过该指针(引用)调用同名覆盖方法(虚函数),基类指针指向哪个派生类对象,就会调用哪个派生类的覆盖方法,称为多态。pbase->show();......
  • Day55 多态
    多态什么是多态即同一方法可以根据发送对象的不同而采用多种不同的行为方式。一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)多态存在的条件有继承关系子类重写父类方法父类引用指向子类对象注意:多态是方法的多态,属性没有多态性。......
  • java多态
    有两个类,一个Animal类,一个Cat类,其中Cat是Animal的子类,此时我在主函数中这样声明一个对象"Animalanimal=newCat();",此时animal实际上是Cat类此时,Animal类中没有catMouse()这个方法,Cat类中有这个方法,我在主函数声明了"Animalanimal=newCat();"后,无法调用animal.catchMouse();......
  • 多态
    publicclassApplication{  publicstaticvoidmain(String[]args){    //一个对象的实际类型是确定的    //可以指向的引用类型就不确定了:父类的引用指向了子类    //Student能调用的方法都是自己的或者继承父类的    Students1=ne......
  • 面向对象之多态和鸭子类型
    【一】多态【1】什么是多态指一类事物有很多形态【2】示例比如汽车是一类,它于很多形态,如奔驰宝马奥迪classCar:defrun(self):print('开始跑')classBenz(Car):defrun(self):super().run()print('98加满')classBwm(Car......
  • 什么是多态
    概念动态编译:类型:可扩展性即同一个方法可以根据发送对象的不同而采取不同的行为方式。一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)多态存在的条件有继承关系子类重写父类方法父类引用指向子类对象注意:多态是方法的多态,属性没有多......
  • 多态和虚函数 [补档-2022-10-23]
    简述:  多态分为两类,一种是静态多态(如函数重载,运算符重载,复用函数名等)和动态多态(派生类和虚函数实现运行时的多态)  静态多态和动态多态的区别是:静态多态的函数地址早绑定,在编译阶段就确定了函数地址。动态多态的函数地址是晚绑定,即运行阶段确定函数地址。​多态的满......
  • 封装、继承、多态
    封装、继承、多态、反射1.封装封装就是将属性隐藏,不让外界发现或使用将可以允许外界使用的内容通过接口开发,让用户通过接口使用隐藏属性的方法是通过__变量名1.1封装之隐藏属性隐藏数据属性classTeacher:def__init__(self,name,age):#将名字和年纪......