Duck键入Vs基于类的继承

时间:2017-05-21 13:11:04

标签: python inheritance duck-typing

使用DuckTyping方法,下面是两个类Duck& Person

class Duck:
   def quack(self):
       print('Quack')

   def fly(self):
       print('Flap')

class Person:
   def quack(self):
       print('I\'m quacking like a duck')

   def walk(self):
       print('Walk')

def quackFlap(creature):
    try: 
       creature.quack()
    except: # EAFP
       print('Cannot quack')

    try:
       creature.flap() # Using hasattr() will violate EAFP
    except: # EAFP
       print('Cannot flap') 

donald = Duck()
quackFlap(donald)

p = Person()
quackFlap(p)  # Duck Typing approach says, Person is not Duck.

使用基于类的继承方法,下面是两个类Bird& Duck

class Bird(object):
   def quack(self):
       print('Quack')

   def fly(self):
       print('Fly')

class Duck(Bird):
   def quack(self):
       print('I\'m quacking like a duck')
   def fly(self):
       print('Flap')

def quackFlap(creature):
    if isinstance(creature, Bird):
       creature.quack()
       creature.flap()

b = Bird()
quackFlap(b)

d = Duck()
quackFlap(d) # Inheritance allowed isinstance() check - Error handling

问题:

1)DuckTyping是否避免了子类化?因为在子类化上,我们没有看到DuckTyping方法的必要性

2)当DuckTyping比基于类的继承更好?

1 个答案:

答案 0 :(得分:5)

  

1)DuckTyping是否避免了子类化?因为在子类化上,我们这样做   不是DuckTyping方法的必要性

完全没有。当您需要访问未在超类上定义的内容时,Duck类型只会变为不需要对子类类型进行强制转换/检查。但是通过良好的设计和正确使用多态,您可以避免这样做(使用instanceof + cast来访问子类的特殊性)。

  

2)当DuckTyping比基于类的继承更好吗?

这实际上取决于......当类之间没有“IS A”关系时,应该避免继承,主要是当它被用作重用代码的意思时。当存在“IS A”关系,并且代码依赖于“instanceof”的使用时,它表示设计不良,即多态性未被正确使用。

例如,鸭子打字是一种获取多态代码的便捷方式,而不依赖于Java之类的抽象类/接口。但是抽象类/接口定义了一个契约。使用duck typing,由于缺乏正式关系,您可以在代码中引入细微的错误。如果你的“嘎嘎”根本不是“嘎嘎”,你就会遇到麻烦。对于继承,由于子类化抽象类的契约性质,这种情况不太可能发生。