2016-05-05 26 views
1

首先,我對Go很新,所以請原諒任何術語上的失誤或錯誤。我懷疑我的術語缺乏指令也是部分原因,因爲在經過數小時的查找之後沒有找到對以下問題的答案。訪問嵌入式功能中的功能

總之,我想下面的代碼的輸出是

I am the Adult 
I am the Child 

如果不是輸出是

I am the Adult 
I am the Adult 

代碼:

package main 

import "fmt" 

type Human struct { 
    age uint 
    name string 
} 

func (h Human) sayName() error { 
    fmt.Println("I am the Adult") 
    return nil 
} 

func (h Human) Introduce() error { 
    h.sayName() 
    return nil 
} 

type Child struct { 
    Human 
} 

func (c Child) sayName() error { 
    fmt.Println("I am the Child") 
    return nil 
} 

func main() { 
    h := Human{} 
    h.Introduce() 

    c := Child{Human{}} 
    c.Introduce() 
} 

所以在本質上,雖然Introduce()只在嵌入類型Human中實現,但它調用sayName(),它在嵌入式中都實現類型和嵌入類型。

據我所知,目前的輸出是這樣的,因爲嵌入式Human結構並不「知道」它是嵌入式的,因此永遠不會調用Child.sayName,只會調用它自己的sayName()函數。

有沒有一種方法來實例化一個Human結構(或一個嵌入結構的結構體),您可以在其中使用替代sayName()函數「替換」Human.sayName()?

回答

1

獲得這種遲後行爲的方式是使用接口。如果Introduce是需要sayName方法的接口上的一種方法,那麼HumanChild都將滿足該接口,並且它們本身可以是Introduce,並且在任一情況下都會調用適當的方法,因爲它將通過接口類型,而不是通過Human

+0

我想我明白你的意思了。代替Introduce()是一個被任何特定結構體接收的函數,它改變爲沒有定義接收器的函數,而是將**作爲參數**一個「說話人」接口,其中說話人被定義爲一個結構實現sayName()? – davidr

+0

@ user306537是的。可悲的是,不允許使用接口接收器定義方法(這將允許接口充當角色)。 – hobbs

0

我一直在想這個問題。正如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) 
}