PHP の interface なめんな を読みました。
Python も非 Duck typing の良さを順調に取り込んでいます。 Python で上記記事のサンプルを書くと
from __future__ import print_function # for Python 2/3 compatibility import abc class Renderable(metaclass=abc.ABCMeta): def prepare(self, name): self.name = name @abc.abstractmethod def render(self): pass class Element(Renderable): def __init__(self, text): self.text = text def render(self): return '<{name}>{text}</{name}>'.format(name=self.name, text=self.text) def render(obj): if isinstance(obj, Renderable): obj.prepare('elem') print(obj.render()) else: print(obj) render(Element('123')) render('123')
ABC の魅力は、 isinstance チェックをカスタマイズできる所で Duck typing と static interface の適した方を選べることなのですが、とりあえずデフォルトのままで intarface 代わりにはなってます。
ちなみに、 Python は多重継承が使えるので、 abstractmethod を使わないで普通のクラスでも何とかなります。
class IRenderable(object): def prepare(self, name): self.name = name def render(self): raise NotImplementedError class Element(IRenderable): def __init__(self, text): self.text = text def render(self): return '<{name}>{text}</{name}>'.format(name=self.name, text=self.text)
さらに、 Python はオーバーロードすら部分的に取り込もうとしています。 PEP 443 が accept されたので、 Python 3.4 では render が次のように書けると思います。
from functools import singledispatch @singledispatch def render(obj): print(obj) @render.register(Renderable): def render(renderable): renderable.prepare('elem') print(renderable.render())