エンジニアはこわくない

好きなように書く

golangのインターフェースが本当に少しだけ理解できたかもしれない。これがポリモーフィズムなのか?


スポンサーリンク

f:id:tsujitaku50:20170224131252j:plain

こんにちは、つじたく(@Tsuji_Taku50)です。

先日こんな記事を書きました。

tsujitaku50.hatenablog.com

今もこの気持は変わってません笑。

やっぱりgolangのインタフェース機能を使いこなせる気がしませんが、少しだけインタフェースの使い所が分かったような気がしたので

書きたいと思います。

あくまでインタフェースの使い方の1つで、まだまだ勉強中なので間違いがあれば教えて下さい。

この記事の一番下に参考にさせて頂いた記事を載せています!

基本的に参考記事を読んで自分で理解するために書いているので内容がかぶってしまう部分もあると思いますm(__)m

インタフェースを使う場合と使わない場合

インタフェースを使わない場合

まずはインターフェースを使わない場合です。

// 構造体を宣言
type Bus struct {
    speed int
}

type Bike struct {
    speed int
}

// Bus構造体のメソッド
func (b *Bus) Run(speed int) string {
    b.speed = speed
    return strconv.Itoa(b.speed) + "Kmで走っています"
}

// Bus構造体のメソッド
func (b *Bus) Stop() {
    b.speed = 0
    fmt.Println("Busはstopしました")
}

// Bike構造体のメソッド
func (b *Bike) Run(speed int) string {
    b.speed = speed
    return strconv.Itoa(b.speed) + "Kmで走っています"
}

// Bike構造体のメソッド
func (b *Bike) Stop() {
    b.speed = 0
    fmt.Println("Bikeはstopしました")
}

// 関数
func BusDrive(b *Bus, speed int) {
    fmt.Println(b.Run(speed))
    b.Stop()
}

// 関数
func BikeDrive(b *Bike, speed int) {
    fmt.Println(b.Run(speed))
    b.Stop()
}

func main() {

    bus := &Bus{
        speed : 0,
    }

    bike := &Bike{
        speed:0,
    }

    BusDrive(bus, 30)
    BikeDrive(bike, 50)
}

上記のコードを見ると、BusDrive関数とBikeDrive関数が存在してます。

ただこの2つの関数は用途は同じです。

今はBusとBikeだけなのでこのままでいいかもしれませんが

今後TruckやAirplaneなどが増えていった場合、その分だけ同じ用途の関数が増えることになります。

これは良くありません。

そこでインターフェースを活用します。

インタフェースを使う

// インターフェース定義
type Vehicle interface {
    Run(int) string
    Stop()
}

type Bus struct {
    speed int
}

type Bike struct {
    speed int
}

// Bus構造体はVehicleインターフェースを満たしている
func (b *Bus) Run(speed int) string {
    b.speed = speed
    return strconv.Itoa(b.speed) + "Kmで走っています"
}

func (b *Bus) Stop() {
    b.speed = 0
    fmt.Println("Busはstopしました")
}

// Bike構造体はVehicleインターフェースを満たしている
func (b *Bike) Run(speed int) string {
    b.speed = speed
    return strconv.Itoa(b.speed) + "Kmで走っています"
}

func (b *Bike) Stop() {
    b.speed = 0
    fmt.Println("Bikeはstopしました")
}

func VehicleDrive(v Vehicle, speed int) {
    fmt.Println(v.Run(speed))
    v.Stop()
}

func main() {

    bus := &Bus{
        speed:0,
    }

    bike := &Bike{
        speed:0,
    }

    // 同じ関数で処理できる
    VehicleDrive(bus, 30)
    VehicleDrive(bike, 20)
}

インターフェースを使用した場合、関数を1つに纏めることが出来ます。

Bus構造体とBike構造体はRunメソッドとStopメソッドを実装しているので、Vehicleインターフェースとして振る舞うことが可能です。

Vehicleインターフェースを引数に関数を作成すれば、上記のようなことが実現可能です。

まとめ

golangのインターフェース・・・

奥が深い・・・

この記事で書いてあるコードは下記Githubに載せてあります。↓

github.com

参考記事

こちらの記事がものすごく参考になりました!↓

Go言語におけるポリモーフィズム インタフェース - はじめてのGo言語