35、面向对象-多态

一、前提概要

Python是否支持多态的问题争论已久,在面向对象语言中,有三大特性(封装 继承 多态)Python作为典型的面向对象语言,怎么可能会不支持多态呢?

产生这个问题的原因在于Python是一门动态编程语言,在运行的时候可以更改自己的结构。在java等面向对象语言中,定义一个变量,强制要求首先声明他的数据类型;而在Python中,这个步骤是完全可以忽略的。由于Python动态语言的特性,Python天生就支持多态,不需要像其他面向对象的语言那样使用了多态语法来实现多态的特性。大家争论Python是否支持多态,其实都是纠结在Python没有多态的语法。

  • 在Java中,如果一个变量被声明是int类型,如果被赋值为一个字符串对象,那一定会报错。在像Java这种强类型的语言中,一个变量被声明数据类型时候,只允许被这个类或这个类的派生类赋值。
  • 而在Python中,声明一个变量,你可以给他赋任何类型的值(对象)

多态可以简单的理解为多种形态,多种类型。在Python中,不需要特殊的多态语法来实现多态的特性

不管Python支不支持多态其实对我们普通的程序员并不是那么重要,关键还是要看能不能解决我解决我们在世界开发中的一些问题。套用一句广告词,广告好不好不重要,关键看疗效!!!

二、多态

1、概念

面向对象程序设计最有趣的特性是多态,它是是让大多数人犯晕的特性。多态意思是有多种形式。指的是一类事物有多种形态。

例如:

  1. 动物有多种形态:鼠,牛,虎,兔,猪,狗,牛,羊,
  2. 序列类型有多种形态:字符串,列表,元组

注: 在静态语言里多态的概念依赖于继承

2、举个栗子

  1. 栗子1
    class Animal(object): #在定义角度来讲
        def __init__(self, name):
            self.name = name
        def talk(self):
            raise NotImplementedError("Subclass must implement abstract method")
    class Cat(Animal):#动物形态1 猫
        pass
    class Dog(Animal):#动物形态2 狗
         pass
    class Duck(Animal):
        pass
    
  2. 栗子2
    class File(): #同一类事物:文件
        def click(self):
            pass
    class Text(File): #文件的形态之一:文本文件
        def click(self):
            pass
    class ExeFile(File): #文件的形态之二:可执行文件
        def click(self):
            pass
    class ImageFile(File): #文件的形态之二:图片形式的文件
        def click(self):
            pass
    

三、鸭子类型

1、概念

python是一种动态语言,崇尚鸭子类型。以下是维基百科中对鸭子类型得论述

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为鸭的对象,并调用它的走和叫方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的走和叫方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的走和叫方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。
鸭子类型通常得益于不测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。从静态类型语言转向动态类型语言的用户通常试图添加一些静态的(在运行之前的)类型检查,从而影响了鸭子类型的益处和可伸缩性,并约束了语言的动态特性。

2、举个栗子

  1. 栗子
    class Bird(object):
        def walk(self):
            pass
        def swimming(self):
            pass
    class Duck(Bird):
        def walk(self):
            print('鸭子大摇大摆的走着!!!')
        def swimming(self):
            print('鸭子悠闲的在水里游着!!!')
    class Goose(Bird):
        def walk(self):
            print('鸭子大摇大摆的走着!!!')
        def swimming(self):
            print('鸭子悠闲的在水里游着!!!')
    class Person(object):
        def __init__(self, name):
            self.name = name
        def walk(self):
            print(self.name + '大摇大摆的走着!!!')
        def swimming(self):
            print(self.name + '悠闲的在水里游着!!!')
    class Test:
        @staticmethod
        def walk(animal):
            animal.walk()
        @staticmethod
        def swimming(animal):
            animal.swiming()
    if __name__ == '__main__':
        duck = Duck()
        person = Person('小明')
        Test.walk(duck)
        Test.walk(person)
    
    说明:
    这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。
    静态语言和动态语言
    • 对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用walk()`方法。
    • 对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个walk()方法就可以了
      鸭子类型通常得益于不检测方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。

四、多态性

1、概念

多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。

多态意味着就算不知道变量所引用的对象类是什么

通俗的来讲可对不同类的对象使用同样的操作

2、举个栗子

  1. 栗子
    class Bird(object):
        def walk(self):
            pass
        def swimming(self):
            pass
    class Duck(Bird):
        def walk(self):
            print('鸭子大摇大摆的走着!!!')
        def swimming(self):
            print('鸭子悠闲的在水里游着!!!')
    class Goose(Bird):
        def walk(self):
            print('鸭子大摇大摆的走着!!!')
        def swimming(self):
            print('鸭子悠闲的在水里游着!!!')
    class Person(object):
        def __init__(self, name):
            self.name = name
        def walk(self):
            print(self.name + '大摇大摆的走着!!!')
        def swimming(self):
            print(self.name + '悠闲的在水里游着!!!')
    class Test:
        @staticmethod
        def walk(animal):
            animal.walk()
        @staticmethod
        def swimming(animal):
            animal.swiming()
    if __name__ == '__main__':
        duck = Duck()
        person = Person('小明')
        Test.walk(duck)
        Test.walk(person)
    

3、为什么要用多态性

  1. 可替换性(substitutability)。多态对已存在代码具有可替换性。
  2. 可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能
    软件设计原则中的 “开闭”原则:
    1. 对扩展开放:允许新增Animal子类;
    2. 对修改封闭:不需要修改依赖Animal类型的等函数。
  3. 灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
  4. 简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容

  • 初识面向对象 楔子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏,你就思考呀,人狗作战...
    go以恒阅读 923评论 0 6
  • 1.1面向对象 面向对象(object-oriented ;简称: OO)至今还没有统一的概念 我这里把它定义为:...
    TENG书阅读 566评论 0 0
  • 抽象类 什么是抽象类 与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的...
    go以恒阅读 607评论 0 3
  • 每个宝宝都要经历这么一个喜欢抓、捏、撕、按、压、扭、插、扔一切东西的过程。这符合宝宝成长中的发展发育规律。萱萱也有...
    萱萱_妈妈阅读 161评论 0 0
  • 说到分布式开发Zookeeper是必须了解和掌握的,分布式消息服务kafka 、hbase 到hadoop等分布式...
    欢醉阅读 1,531评论 0 7