トラック
/
Go
Go
/
演習
/
空港ロボット
空港ロボット

空港ロボット

学習演習

はじめに

メソッドの集まりとしてのインターフェース

最も単純な形では、インターフェース型はメソッドのシグネチャの集まりです。 次は、AddとValueという2つのメソッドを含むインターフェース定義の例です。

type Counter interface {
    Add(increment int)
    Value() int
}

incrementのような仮引数の名前は、インターフェース定義から省略できますが、書いておくと読みやすくなることがよくあります。

Goのインターフェース名には、InterfaceやIという語は含めません。 その代わり、ReaderやStringerのように、erで終わることがよくあります。

インターフェースを実装する

インターフェースのメソッドを定義している型は、自動的に、暗黙のうちにそのインターフェースを「実装」します。 Goにはimplementsというキーワードはありません。

次の型は、上で見たCounterインターフェースを実装しています。

type Stats struct {
    value int
    // ...
}

func (s Stats) Add(v int) {
    s.value += v
}

func (s Stats) Value() int {
    return s.value
}

func (s Stats) SomeOtherMethod() {
    // The type can have additional methods not mentioned in the interface.
}

インターフェースを実装するうえでは、メソッドが値レシーバーを持つかポインターレシーバーを持つかは関係ありません。 (これらについて自信がなければ、メソッドのコンセプトをもう一度見てみましょう。)

インターフェース型の値には、それらのメソッドを実装している任意の値を入れることができます。 [^1]

つまりStatsは、Counterインターフェースを期待するすべての場所で使えるようになりました。

func SetUpAnalytics(counter Counter) {
    // ...
}

stats := Stats{}
SetUpAnalytics(stats)
// works because Stats implements Counter

インターフェースは暗黙のうちに実装されるので、1つの型が複数のインターフェースを簡単に実装できます。 必要なメソッドがすべて定義されていればよいのです。

空のインターフェース

Goには、とても特別なインターフェース型が1つあります。メソッドを1つも持たない空のインターフェース型です。 空のインターフェースはinterface{}のように書きます。 anyはinterface{}のエイリアスで、よりよく使われます。

空のインターフェースにはメソッドがないので、どの型も暗黙のうちにこれを実装しています。 これは、あらゆる値を汎用的に受け取る関数を定義するのに役立ちます。 その場合、関数の仮引数に空のインターフェース型を使います。

説明

ベルリンにある新しい空港が、ロボット研究室のためにエンジニアを採用しました。そこで働き始めることになります。 空港には、ぎこちなくて、どこか人型に見えるロボットたちがいて、カスタマーサービスの改善に使おうとしています。

最初の仕事は、セルフチェックインカウンターでパスポートをスキャンした人に、その人の母語でロボットがあいさつできるようにするプログラムを書くことです。

ロボットは自分の能力に誇りを持っているので、いつも最初に自分が話せる言語を告げてから、その人にあいさつします。 たとえば、ドイツのパスポートをスキャンした場合、ロボットはこう言います。

I can speak German: Hallo Dietrich!

1. あいさつ機能を抽象化する

言語ごとのコードを自分で書くわけではないので、あとから他のエンジニアが簡単に言語を追加できるように、ロボットのコードを構成する必要があります。

まずは、2つのメソッドを持つインターフェースGreeterを定義します。

  • LanguageNameは、ロボットがその訪問者にあいさつする言語の名前(string)を返します。
  • Greetは、訪問者の名前(string)を受け取り、特定の言語でのあいさつメッセージをstringで返します。

次に、訪問者の名前と、Greeterインターフェースを実装しているものを受け取り、目的のあいさつの文字列を返す関数SayHelloを実装します。 たとえば、LanguageNameが"German"を返し、Greetが"Hallo {name}!"を返すドイツ語のGreeter実装を考えてみましょう。

SayHello("Dietrich", germanGreeter)
// => "I can speak German: Hallo Dietrich!"

2. イタリア語を実装する

次は、イタリアのパスポートをスキャンした人にロボットが対応できるようにします。

そのために、構造体Italianを作成し、タスク1で用意したGreeterインターフェースを満たすために必要な2つのメソッドを実装します。 イタリア語では、"Ciao {name}!"であいさつできます。

3. ポルトガル語を実装する

今日の仕事を終える前に、ポルトガル語であいさつする機能も仕上げておきましょう。

そのために、構造体Portugueseを作成し、ここでもGreeterインターフェースを満たすために必要な2つのメソッドを実装します。 ポルトガル語では、"Olá {name}!"であいさつできます。

GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Go Exercism

空港ロボットを始める準備はできましたか?

Exercismに登録すれば、34個のコンセプト166個の演習、そして本物の人間によるメンタリングとともに、Goを学んでマスターできます。すべて無料です。