まとめようと思ったきっかけ
Go言語を勉強していてinterfaceについて調べたことがある方、特に自分のような初心者の方。
interfaceについて説明してあるページってなんでこんなに分かりにくい表現を使うの?って思ったことありませんか?
これがいわゆるダックタイピングです。
知らねえよ!
Animalというinterfaceは鳴くことができます。
猫:ミャオ
アヒル:グワッ
いや、わかるけど…!わかるけどさ!
なんかもう少し実装のイメージがつく具体例なかったの!?
"If it walks like a duck and quacks like a duck, it must be a duck"
(もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルに違いない)
英語の授業ですか!?
なぜこのような説明が多いのか
ひとえに「高いレベルのもの=抽象的なもの」であることが理由であるような気がします。
また、「高いレベルの人間でありたい=抽象的な理解をしたい」という考えは当然です。
単純な算数ドリルを勉強して、難しい応用問題を解けるようになる。
それは当たり前のこと。
でも、
自分にとってはこの動物の例えとかダックタイピングの話がとても分かりにくかったんです。
実際に自分が実装しているものにinterfaceがどう必要なのか、それを直接的に知りたかった…。
が、調べても「グワッ」とか「ミャオ」とか可愛い話か難しすぎる話ばかり…。
自分の見解
ここに示す自分の見解はgoで書かれたコードを読みとくとき、また、「interfaceで定義して書いといて」とか言われたときの話です。
はじめに結論
Go言語におけるinterface型は、なんでも屋さん!
(intやstring等の型を指定しなくて良いもの)
なにを代入しても良いもの。
ただし、「なにを代入しても良い」と言ってもさすがにどんなものを代入しても良いってわけにもいかない時があるので、それを指定することもできるもの。
なんでも屋さん
例えば型をチェックする「型チェッカー関数」を定義しましょう。
当然、どんな型でもチェックできるように型チェッカー関数の引数はinterface型になります。
コードにするとこんな感じ?
func 型チェッカー(i interface{}) {
return iの型名 + "です"
}
これでどんな変数を入れても型名を返す関数ができました。
「なにを代入しても良い」わけにはいかないとき
どんな型のものでも良いわけではないけど、ある程度なんでも屋さんを実装したいとき。
そんなときは最低限必要なものを決めたinterface型を定義します。
type メールサービス interface {
送信(内容) error
}
これで「送信」ができるものだったらなんでも良いinterface型ができます。
実際には下記のようにinterface型に適当な構造体が代入され、条件分岐のような処理が行われます。
初心者の僕らにとっては経験もないし実際の実装のイメージも湧かないので、とりあえずinterface{}
の{}
の中になにか関数が書いてあれば、「その名前の関数がどこかに定義されていれば、どんなものを代入しても良い入れ物」ができたと認識すれば良いでしょう。
interfaceの{}
の中身は必ず関数です!関数以外は入りません!
→関数以外にもinterfaceも入れることができると指摘を受けました。 (詳細はコメント欄)
こんなときはどう理解する?
interface型が引数となっている関数
どんなものも引数として扱うことができる関数。
もしくはinterface{なんちゃら}
と{}
の中身になにか関数が書いてあったら、その名前と同じ名前の関数が定義されている構造体だったらなんでも引数として扱える関数。
その名前と同じ名前の関数が定義されている構造体
が難しかったらGo言語のメソッドについての記事を調べてみてください。
他の言語でクラスとかやってたら文法の理解は容易なはず…!
interface型が戻り値になっている関数
どんな型の値でも返す関数。
もしくはinterface{なんちゃら}
と{}
の中身になにか関数が書いてあったら、おそらく{}
内の関数をその後に処理するだろうと思われる戻り値を返す関数。
自分でinterface型を定義するとき
おそらく上記のメールサービスの例のように、同種であるがいくつかの異なるapiサービスを使うことが考えられる状況のとき。考え方としてはif分岐と一緒だと思う。
まとめ
- interface型はなんでも屋さん。
- なんでも良すぎてもよくない場合があるので、特定の関数名をもつ構造体のみに限定させることもできる。
interface{}
の{}
の中身は必ず関数が入る-
interface{}
の{}
の中身はだいたい関数が入る。あとインターフェースも入る。
低レベルで結局分かりづらい内容の記事となってしまいましたが、誰かの理解が進めば幸いです。