python语言的鸭子类型和强类型语言的多态

Posted wxm422562

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python语言的鸭子类型和强类型语言的多态相关的知识,希望对你有一定的参考价值。

python语言的鸭子类型和强类型语言的多态

 

  前面讲接口类的时候举过一个有关支付方式的例子,支付方式可以有几种,微信支付,支付宝支付,苹果支付等,这几个不同的支付都统一于支付,像这样几个类都统一于

某一个类或者某一个方法,或者说一个类有不同的形态的情况就属于多态;虽然几种支付方式都归一于支付类,执行的方法一样,但是每一个支付方式都有自己的特性,实现的

形态也不一样,即为多态性。

class Payment:  # 必要的父类
    def pay(self,money):
        pass
class Wechatpay(Payment):  # 子类继承父类 
    def pay(self,money):
        print(已经使用微信支付了%s元 % money)

class Alipay(Payment):  # 子类继承父类
    def pay(self,money):
        print(已经使用支付宝支付了%s元 % money)

class Aapplepay(Payment):  # 子类继承父类
    def pay(self,money):
        print(已经使用苹果支付了%s元 % money)

def pay(pay_obj,money):  # 受到父类的约束,这里的pay_obj只能传入继承了父类的子类
    # 统一支付入口,归一化设计,不管使用哪种方式,都统一于支付方法
    pay_obj.pay(money)

 

也可以不用在前面加上一个父类对子类进行约束也可以达到多态的效果

 
class Wechatpay():
    def pay(self,money):
        print(已经使用微信支付了%s元 % money)

class Alipay():
    def pay(self,money):
        print(已经使用支付宝支付了%s元 % money)

class Aapplepay():
    def pay(self,money):
        print(已经使用苹果支付了%s元 % money)

def pay(pay_obj,money):  # 这里的pay_obj对数据不敏感,只要是含有pay方法的都可以传入
    # 统一支付入口,归一化设计,不管使用哪种方式,都统一于支付方法
    pay_obj.pay(money)

pay(Aapplepay(),10000)  # 这里可以随意的传入支付方式,只要传入的方式里面有归一的pay方法

  因为在python里面传参的时候:def pay(pay_obj,money),对数据不敏感,所以可以完全不用借助父类来表现出多态,像python这样不必需要一个父类来约束子类就可以形成多态的类型叫做鸭子类型。所以说python天生支持多态,属于动态强类型语言。

但是其他语言比如Java必须借助class Payment父类来传父类的数据类型才可以,用父类来约束子类,如果传的不是父类的数据类型则会报错,这样的类型情况才是属于正真的多态,也就是强类型语言中的多态。

  python(鸭子类型):不崇尚根据继承所得来的相似,我只是自己实现自己的代码就可以了。如果两个类刚好相似,并不产生父类的子类的兄弟关系就是鸭子类型。比如list 和tuple就是这样的关系,它们本身有好多相似的方法,但是并没有通过父类去约束而找出相似的地方,只是我们自己写代码的时候自我约束。

  鸭子类型的优缺点:

  优点:松耦合,每个相似的类之间都没有影响,删除或修改一个类的代码不会影响其他类的

  缺点:太随意,只能自己写代码自觉约束

再用一个比较好理解的例子来说明python语言的鸭子类型和强类型语言的多态:list 和 tuple

鸭子类型:

class List():
    def __len__(self):pass
class Tuple():
    def __len__(self):pass
def len(obj):
    return  obj._len_()
l = Tuple()
len(l)  # 这里的l可以是列表也可以是元祖,不管是那个都可以将参数传入len中,只要含有len方法都可以传入

强类型语言的多态:

class Foo:pass  # 必须有一个父类
class List(Foo):  # 子类要继承父类
    def __len__(self):pass
class Tuple(Foo):  # 子类要继承父类
    def __len__(self):pass
def len(obj):
    return  obj._len_()
l = Tuple()
len(l)  # 这里的l只能是继承了Foo的类,数据类型必须和Foo的一样,如果上面的obj传入的是list这里的l也必须是list,否则会报错

 总结:接口类和抽象类在python当中的应用点并不是非常必要

以上是关于python语言的鸭子类型和强类型语言的多态的主要内容,如果未能解决你的问题,请参考以下文章

多态/封装

多态,封装

python多态

python 鸭子类型

深入类和对象

Python面向对象之鸭子类型