鸭子打字与基于 class 的继承

Duck typing Vs class based Inheritance

使用 DuckTyping 方法,下面是两个 classes 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.

使用基于class的继承方法,下面是两个classes 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 是否避免了 Subclassing?因为在 subclassing 上,我们没有看到 DuckTyping 方法的必要性

2) DuckTyping 何时优于基于 class 的继承?

1) Does DuckTyping avoid Subclassing? because on subclassing, we do not the necessity of DuckTyping approach

完全没有。当您需要访问超类上未定义的内容时,鸭子类型只会对子类类型进行不必要的 casts/checkings 操作。但是通过良好的设计和正确使用多态性,您可以避免这样做(使用 instanceof + cast 来访问子类的特殊性)。

2) When DuckTyping is better than class based inheritance?

这真的取决于...当 类 之间没有 "IS A" 关系时,应避免继承,主要是当它仅用作重新利用代码的手段时。如果存在 "IS A" 关系,并且代码依赖于 "instanceof" 的使用,则表明设计不当,即未正确使用多态性。

Duck typing 是一种无需依赖抽象 classes/interfaces(例如 Java)即可获得多态代码的简便方法。但是一个抽象 class/interface 定义了一个契约。使用鸭子类型,由于缺乏正式关系,您可以在代码中引入细微的错误。如果你的 "quack" 根本不是 "quack",你就有麻烦了。使用继承,由于子类化抽象的契约性质,这种情况不太可能发生 类.