Go言語触ってみた その3
今週も、Goを触ってみて気になった点とかについてまとめてみる。
先週の振り返り
先週はGoの型システムについてブログを書いた。新しい型を定義する際に、
- 既存の型に別名(?)をつける場合
- struct型を定義する場合
- interface型を定義する場合
の3通りの方法があると述べた。
今週は、先週ちょろっと触れながら詳しくは説明しなかったembedding type
について触れる。
embedding typeとは?
Goにおいては、structやinterfaceを定義する際にembedding(埋め込み)
を行う事が出来る。このとき、structとinterfaceそれぞれでembeddingの意味合いは異なってくるので順に説明する。
interfaceにおけるembedding
interfaceにおけるembeddingの方が単純で分かり易いので、まずこちらについて説明する。
interafaceは「特定のメソッドが存在する事を保証する仕組み」な訳だけど、interfaceにおいてembeddingを行う事で、埋め込まれたinterfaceの性質を受け継ぐ事が出来る。
例えば、ReaderとWriterというinterface型が存在する時に
type ReadWriter interface { Reader Writer }
というReadWriter型の定義があると、ReaderとWriterの両方の性質を満たす値をReadWriter型として受け取る事が出来る様になる。
すなわち、例えば次の例の様にReader型の定義がReadメソッドが定義されている事、Writer型の定義がWriteメソッドが定義されてる事とすると、ReaderとWriterを埋め込んだReadWriter型はReadメソッドとWriteメソッド両方が定義された型という事になる。
type Reader interface { Read(p []byte) (n int, err error) } type Writer interface { Write(p []byte) (n int, err error) } // この時、上で定義したReadWriter型は次の様に定義したものと同じになる type ReadWriter interface { Read(p []byte) (n int, err error) Write(p []byte) (n int, err error) }
文字通り、 interface型にinterface型が埋め込まれて いるのが分かる。
structにおけるembedding
interfaceにおけるembeddingは分かり易かったが、structにおけるembeddingはちょっとややこしい。
interfaceにおいては埋め込まれるのはinterfaceのみであったが、structにおいては任意の型を埋め込む事が出来る。 例えば、interface型のReaderとWriterを埋め込んだStructReadWriter型を作る事が出来る。
type StructReadWriter struct { Reader // Readerはinterface型 Writer // Writerはinterface型 }
このとき、StructReadWriter型の値はReaderやWriterをフィールドとして持ち、さらにReaderやWriterにただ処理を委譲するだけのReadメソッドやWriteメソッドを持つ事になる。すなわち、structにおける埋め込みを行った上記のコードは次のコードと等価である。
type StructReadWriter struct { Reader Reader // Readerというフィールド名でReader型の値を持つ Writer Writer // Writerというフィールド名でWriter型の値を持つ } func (srw StructReadWriter) Read(p []byte) (n int, err error) { return srw.Reader.Read(p) // ReaderフィールドのReadメソッドを呼び出し } func (srw StructReadWriter) Write(p []byte) (n int, err error) { return srw.Writer.Write(p) // WriterフィールドのWriteメソッドを呼び出し }
structにおいてembeddingを行うと任意の型の実装を受け継ぐ事が出来るため、 継承 と同様の機能を果たす事が出来る。ただし、実際には継承とは異なる点に注意しなければならない。
まとめ
Go言語において、embedding type
は広く使われる。
作者達としては継承よりもより一般性の高いアプローチらしく、興味深く感じた。