Duck typing and (java) interface concept

Viewed 4715

I just read the Wikipedia article about duck typing, and I feel like I miss an important point about the interface concept I used to in Java:

"When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck."


class Duck:
    def quack(self):
        print("Quaaaaaack!")
    def feathers(self):
        print("The duck has white and gray feathers.")
    def swim(self):
        print("Swim seamlessly in the water")

class Person:
    def quack(self):
        print("The person imitates a duck.")
    def feathers(self):
        print("The person takes a feather from the ground and shows it.")
    def name(self):
        print("John Smith")

def in_the_forest(duck):
    duck.quack()
    duck.feathers()

def game():
    donald = Duck()
    john = Person()
    in_the_forest(donald)
    in_the_forest(john)

game()

what if, in in_the_forest, I write:

  • does it quack like a duck ? yes
  • does it have a duck feathers ? yes
  • great, it's a duck we've got !

and later, because I know it's a duck, I want it to swim? john will sink!

I don't want my application to crash (randomly) in the middle of its process just because John faked to be a duck, but I guess it wouldn't be a wise idea to check every single attributes of the object when I receive it ... ?

4 Answers

The dynamic typing strength, Duck Typing has another card up its sleeve, to enable implementing multiple interfaces, i.e. multiple independent behaviour traits.

Formal Interfaces, using ABCs are great and can gives you early failure. However you can still only implement one 'interface' at a time (you can inherit from one parent class).

Besides, using class inheritance you soon end up in a mess due to its innate chain and lead to tight coupling and blind alleys. An error due to a change up the chain will impact all the related code which may not have been tested nor have full test coverage.

Whereas classes that use composition instead promote independency. A dev can plan the UML with necessary interfaces to add multiple behaviour traits (e.g. ILogger, IEventGenerator, ICalcArea...) and in the code mask the multiple interfaces using duck typing. Of course the drawback is the dev needs to plan carefully to prevent name collisions and as the OP points out, missing a property or method will end as a runtime error rather than compiler warning.

Back to the old strength / weakness trade in.

Related