python语言的鸭子类型和强类型语言的多态python
前面讲接口类的时候举过一个有关支付方式的例子,支付方式能够有几种,微信支付,支付宝支付,苹果支付等,这几个不一样的支付都统一于支付,像这样几个类都统一于微信
某一个类或者某一个方法,或者说一个类有不一样的形态的状况就属于多态;虽然几种支付方式都归一于支付类,执行的方法同样,可是每个支付方式都有本身的特性,实现的app
形态也不同,即为多态性。微信支付
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)
也能够不用在前面加上一个父类对子类进行约束也能够达到多态的效果spa
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父类来传父类的数据类型才能够,用父类来约束子类,若是传的不是父类的数据类型则会报错,这样的类型状况才是属于正真的多态,也就是强类型语言中的多态。code
python(鸭子类型):不崇尚根据继承所得来的类似,我只是本身实现本身的代码就能够了。若是两个类恰好类似,并不产生父类的子类的兄弟关系就是鸭子类型。好比list 和tuple就是这样的关系,它们自己有好多类似的方法,可是并无经过父类去约束而找出类似的地方,只是咱们本身写代码的时候自我约束。blog
鸭子类型的优缺点:继承
优势:松耦合,每一个类似的类之间都没有影响,删除或修改一个类的代码不会影响其余类的接口
缺点:太随意,只能本身写代码自觉约束
再用一个比较好理解的例子来讲明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当中的应用点并非很是必要