Goでは、インターフェースがデータではなく機能を定義するという事実に精通しています。一連のメソッドをインターフェイスに配置しましたが、そのインターフェイスを実装するものに必要なフィールドを指定できません。
例えば:
// Interface
type Giver interface {
Give() int64
}
// One implementation
type FiveGiver struct {}
func (fg *FiveGiver) Give() int64 {
return 5
}
// Another implementation
type VarGiver struct {
number int64
}
func (vg *VarGiver) Give() int64 {
return vg.number
}
これで、インターフェースとその実装を使用できます。
// A function that uses the interface
func GetSomething(aGiver Giver) {
fmt.Println("The Giver gives: ", aGiver.Give())
}
// Bring it all together
func main() {
fg := &FiveGiver{}
vg := &VarGiver{3}
GetSomething(fg)
GetSomething(vg)
}
/*
Resulting output:
5
3
*/
さて、あなたができないことは次のようなものです:
type Person interface {
Name string
Age int64
}
type Bob struct implements Person { // Not Go syntax!
...
}
func PrintName(aPerson Person) {
fmt.Println("Person's name is: ", aPerson.Name)
}
func main() {
b := &Bob{"Bob", 23}
PrintName(b)
}
しかし、インターフェースと埋め込まれた構造体をいじった後、私はこれを行う方法を発見しました:
type PersonProvider interface {
GetPerson() *Person
}
type Person struct {
Name string
Age int64
}
func (p *Person) GetPerson() *Person {
return p
}
type Bob struct {
FavoriteNumber int64
Person
}
構造体が埋め込まれているため、BobにはPersonが持っているすべてのものがあります。また、PersonProviderインターフェースを実装しているため、そのインターフェースを使用するように設計された関数にBobを渡すことができます。
func DoBirthday(pp PersonProvider) {
pers := pp.GetPerson()
pers.Age += 1
}
func SayHi(pp PersonProvider) {
fmt.Printf("Hello, %v!\r", pp.GetPerson().Name)
}
func main() {
b := &Bob{
5,
Person{"Bob", 23},
}
DoBirthday(b)
SayHi(b)
fmt.Printf("You're %v years old now!", b.Age)
}
上記のコードを示すGo Playgroundは次のとおりです。
この方法を使用すると、動作ではなくデータを定義するインターフェースを作成できます。これは、そのデータを埋め込むだけで、任意の構造体で実装できます。その埋め込みデータと明示的に相互作用し、外部構造体の性質を認識しない関数を定義できます。そして、すべてはコンパイル時にチェックされます!(私が見ることができる、あなたが混乱することができる唯一の方法は、インターフェースを埋め込むことですPersonProvider
Bob
は、具体的なではなくにをPerson
です。それは実行時にコンパイルして失敗します。)
さて、これが私の質問です。これはきちんとしたトリックですか、それとも別の方法で行う必要がありますか?