m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

go言語の学習:ポリモーフィズムのパターン

Javaとかではクラスにinterfaceとか定義して使用する

goの場合は構造体自体はメソッドを実装するが、定義されているインターフェースは定義しない

サンプル
package main

import (
	"fmt"
)


// Sample1インターフェース、メソッドを定義
type Sample1 interface {
	Print()
}

// Hoge構造体、Printメソッドを用意
type Hoge struct {
	a int
}
func (c Hoge) Print() {
	fmt.Println("hoeghoge")
	fmt.Println(c.a)
}

// Foo構造体、Printメソッドを用意
type Foo struct {
	a int
}
func (c Foo) Print() {
	fmt.Println("foofoo")
	fmt.Println(c.a)
}

func main() {
	fmt.Println("start")

	// Sample1インターフェースを定義
	var sample1 Sample1

	// 構造体を生成
	hoge := Hoge{a: 100}
	foo  := Foo{a: 500}

	// sample1変数にHoge構造体を設定して実行
	sample1 = hoge
	sample1.Print()

	// sample1変数に Foo構造体を設定して実行
	sample1 = foo
	sample1.Print()

	fmt.Println("end")
}

interface型に共通の呼び出したいメソッドを定義しておくことで実行することが可能
しかし、この場合はSample1を定義しておかないといけない

var sample1 interface{}

のように定義していないinterfaceを使用した場合は動かすことができるか?

typeで定義されたメソッドを使用前に定義することで
対応は可能、しかし、設定された変数には定義されていないこともあるため、型アサーションで存在チェックすることが必要

	// Sample1インターフェース、メソッドを定義
	type Sample1 interface {
		Print()
	}

	// sample1変数にHoge構造体を設定して実行
	sample1 = hoge
	a, ok := sample1.(Sample1)
	if !ok {
		fmt.Println("Print実行不可")
		return
	}
	a.Print()

所感

まああれかな、JavaでObject型で受け取ってどのクラス情報を保持するかみたいな感じと思います。
今回でいうとinterface型で定義して受け取って入れば対象のinterfaceのメソッドに応じて処理を切り替えられる感じ
interface型の仕組みを上手く理解していないのでこのあたり考えて対応する必要がありそうです。