たまーに考えることがあったが、せっかくなのでアウトプットしておく。
まず前提としてGo以外のインターフェイスを持つ言語、例えばJavaではインターフェイスを満たしていることを明示するためにimplementsキーワードなどで実装を明示してやる必要がある。つまり、実装側がどんなインターフェイスを満たしているかを表明しなければいけない。一方でGoのAccept Interfaceでは実装側には一切の依存が必要なく、むしろダックタイピングに近い。
具体的にAccept Interfaceが効いてくる例として、まずBというインターフェイスを引数として受け取る関数があるとする。仕様変更で、そのインターフェイスBを継承するCというインターフェイスに依存する必要ができた。この場合、Accept Interfaceでない言語の場合には、この変更は実装側の定義を変更して満たしているインターフェイスをBからCに変更せねばならない。つまりインターフェイスに依存する側の変更であるにも関わらず、インターフェイスの実装側にも、本来不要なはずの変更が及ぶこととなる。一方でGoの場合には、インターフェイスが変わったとしても、インターフェイスの実装側には変更は及ばない。
Goのインターフェイスはダックタイピングに限りなく近く、ある程度の型安全を担保しながらもコンストラクタDIなどで注入する型を汎化させることができる。また、Goではインターフェイスは一般的には実装側ではなく、インターフェイスに依存する側(つまりGoではインターフェイスを引数などに指定する側)に属するため、仮に実装を受け取る側の仕様が変わったり、インターフェイスに変更があったりしても、大部分の変更はインターフェイスの実装側に影響を与えない。GoのAccept Interfaceはインターフェイスとして型安全性を維持しながら、さらにアプリケーションのモジュール間の依存関係を最小限にすることができる優れた仕組みであると言える。
なお、万能静的型付け言語として名高いScalaにはStructural Typeとして型安全なダックタイピングをする仕組みがある。やっぱScalaってスゲーな。
- 作者: 松木雅幸,mattn,藤原俊一郎,中島大一,上田拓也,牧大輔,鈴木健太
- 出版社/メーカー: 技術評論社
- 発売日: 2019/08/01
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る