3 回答

TA貢獻1798條經驗 獲得超3個贊
獲得這種后期綁定行為的方法是使用接口。IfIntroduce
是接口上的一個sayName
方法,它需要一個方法,那么Human
和Child
都將滿足該接口,并且可以Introduce
自己滿足,并且sayName
在任何一種情況下都將調用正確的方法,因為它將通過接口類型而不是 via 分派Human
。

TA貢獻1785條經驗 獲得超8個贊
你想做的事情是不可能的。正如你所說,Human
類型永遠無法知道它的嵌入Child
型和為此時Introduce
被調用它沒有調用方式Child
的類型版本sayName()
。您正在嘗試反轉關系,讓嵌入類型在嵌入器中調用其方法的另一個版本。
嵌入類型的方法被提升到嵌入器的范圍,但這是一條單行道,這是明智的。在這種情況下,您只需要以不同的方式構造您的代碼。最有可能的是,您正在尋找的任何行為都可以通過使用接口而不是嵌入來實現。我會提供更多示例,但是對于您的代碼示例,沒什么好說的,顯然要解決這里的問題,您只需調用sayName()
并且永遠不會Introduce
首先定義,因為它什么都不做。
您可能應該只嵌入相反的方向。Human
不包含對的引用,Child
但Child
確實有對Human
和的引用,在這種情況下,兩者都有對 的定義sayName()
,Child
可以Human
通過做來調用's c.Human.sayName()
。所以我的直覺說你嵌入了錯誤的方向,或者你應該使用接口。這純粹是一個假設,但我猜你可能有錯誤的想法,因為你指的Human
是和“成人”(如父母)和Child
作為孩子(就像一個孩子班)。根本不是這種情況。嵌入與組合相同,只是嵌入類型的方法和字段被提升或提升,或者您喜歡說它們被移動到嵌入器范圍的任何術語。話雖如此,我在 SO 上看到了很多關于這個的困惑,這幾乎總是因為提問者把它看作是繼承,而實際上它是組合。

TA貢獻1772條經驗 獲得超8個贊
我想錯了。正如 hobbs 和 evanmcdonnal 所說,“正確”的做法是讓 Introduce() 函數成為一個帶有接口參數的函數,然后創建一個 Child 和 Human 都實現的接口。
以下給出了所需的輸出:
package main
import "fmt"
type Talker interface {
sayName() error
}
type Human struct {
age uint
name string
}
func (h Human) sayName() error {
fmt.Println("I am the Adult")
return nil
}
type Child struct {
Human
}
func Introduce(t Talker) error {
t.sayName()
return nil
}
func (c Child) sayName() error {
fmt.Println("I am the Child")
return nil
}
func main() {
h := Human{}
Introduce(h)
c := Child{Human{}}
Introduce(c)
}
- 3 回答
- 0 關注
- 187 瀏覽
添加回答
舉報