Menu
Coddy logo textTech

インターフェース入門

CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 25/107。

Go の interface は、実装を伴わずに一連の method シグネチャを定義します。これは型が何をできるかを記述するものであり、どのように実行するかを記述するものではありません。interface 内のすべての method を実装する型は、自動的にその interface を満たします。

interfaceを定義する方法は次のとおりです。

type Speaker interface {
    Speak() string
}

この Speaker インターフェースは、これを実装する任意の型に、文字列を返す Speak() メソッドがあることを要求します。これで、このメソッドを持つ任意の構造体を、Speaker が必要とされる場所で使用できます。

type Dog struct {
    Name string
}

func (d Dog) Speak() string {
    return d.Name + " says woof!"
}

type Cat struct {
    Name string
}

func (c Cat) Speak() string {
    return c.Name + " says meow!"
}

DogCat は、それぞれ正しいシグネチャの Speak() メソッドを持っているため、どちらも Speaker インターフェースを満たします。これで、任意の Speaker を受け取る関数を記述できるようになりました。

func MakeSound(s Speaker) {
    fmt.Println(s.Speak())
}

func main() {
    dog := Dog{Name: "Buddy"}
    cat := Cat{Name: "Whiskers"}
    
    MakeSound(dog)  // Buddy は woof! と言う!
    MakeSound(cat)  // Whiskers は meow! と言う!
}

interface の要件を満たす any の型で、基盤となる実装に関係なく動作する、柔軟で再利用可能なコードを記述できます。

challenge icon

チャレンジ

簡単

異なる型が共通の動作を共有できる仕組みをインターフェースで示す、車両の説明システムを構築しましょう。複数の車両型が満たせるインターフェースを作成し、それを使って any 車両を統一的に説明します。

コードを 2 つのファイルに分けて整理します。

  • vehicles.go: 1 つのメソッド Describe() string を持つ Describer インターフェースを Define します。次に、このインターフェースを満たす 2 つの構造体を作成します。
    • CarBrandModel の fields(both とも文字列)
    • BicycleType(文字列)と Gears(int)の fields
    各構造体には、車両について説明する文字列を返す Describe() メソッドを実装します。
  • main.go: any Describer を accepts し、その Describe() メソッドを calling した結果を表示する、PrintDescription という名前の function を作成します。input から車両情報を読み取り、Car と Bicycle の both を作成して、function を使ってそれぞれの説明を表示します。

次の input が提供されます。

  • 1 行目: Car brand
  • 2 行目: Car model
  • 3 行目: Bicycle type
  • 4 行目: Gears の数(整数)

Describe() メソッドは、次の形式の文字列を返す必要があります。

  • Car: [Brand] [Model]
  • Bicycle: [Type] bike with [Gears] gears

たとえば、ToyotaCamryMountain21 が与えられた場合、出力は次のようになります。

Toyota Camry
Mountain bike with 21 gears

重要なポイントは、PrintDescription function が Describe() メソッドを持つ any 型で動作することです。Car、Bicycle、または後で追加する可能性のあるその他の車両型のどれを扱っているかを知る必要はありません。

自分で試してみよう

package main

import (
	"fmt"
)

// TODO: 任意の Describer を受け取る PrintDescription 関数を作成する
// そしてその Describe() メソッドを呼び出した結果を出力する

func main() {
	// 入力を読み取る
	var carBrand string
	var carModel string
	var bicycleType string
	var gears int

	fmt.Scanln(&carBrand)
	fmt.Scanln(&carModel)
	fmt.Scanln(&bicycleType)
	fmt.Scanln(&gears)

	// TODO: 入力からブランドとモデルを使って Car を作成する

	// TODO: 入力からタイプとギアを使って Bicycle を作成する

	// TODO: PrintDescription を使って車の説明を出力する

	// TODO: PrintDescription を使って自転車の説明を出力する
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Goオンラインコンパイラ