正直,何に使えるのよくわかりませんが,以下のようにすると動的にinterface
の実装方法を変更できることに気づきました.
struct
の匿名フィールド(埋め込み)として,interface
を設定すると,そのstruct
も埋め込んだinterface
を実装していることになります.埋め込んだinterface
は匿名フィールドなので,型名でアクセスして入れ替えることができます.
以下の例では,fmt.Stringer
インタフェースの実装を動的に変更しています.
package main
import (
"fmt"
"strings"
)
type StringerFunc func() string
func (sf StringerFunc) String() string {
return sf()
}
type Person struct {
fmt.Stringer
FirstName string
LastName string
Age int
}
func NewPerson(firstName, lastName string, age int) (p *Person) {
p = &Person{
nil,
firstName,
lastName,
age,
}
p.Stringer = StringerFunc(func() string {
return fmt.Sprintf("%s %s (%d)", p.FirstName, p.LastName, p.Age)
})
return
}
func (p *Person) SetStringer(sf func(p *Person) string) {
p.Stringer = StringerFunc(func() string {
return sf(p)
})
}
func main() {
p := NewPerson("Taro", "Yamada", 20)
fmt.Println(p)
p.SetStringer(func(p *Person) string {
return fmt.Sprintf("%s, %s (%d)", strings.ToUpper(p.LastName), p.FirstName, p.Age)
})
fmt.Println(p)
}
上記のプログラムを実行すると,以下のような結果になります.
Taro Yamada (20)
YAMADA, Taro (20)
なんか面白いことに使えそうですが,今のところ思いつきませんでした.
なにか思いついた方はぜひ教えて下さい.