我试图在GO中实现这种多态性方式
type Discoverer interface {
Discover() string
}
type A struct {
}
func (obj A) GetTest() string {
return "im in A"
}
type B struct {
A
}
func (obj B) GetTest() string {
return "im in B"
}
func (obj A) Discover() string {
return obj.GetTest()
}
func main() {
a := A{}
b := B{}
fmt.Println(a.Discover())
fmt.Println(b.Discover())
}
现在我进入输出
im in A
im in A
所以,我的问题是:可以在输出中看到
im in A
im in B
没有"覆盖"发现B?
func (obj B) Discover() string {
return obj.GetTest()
}
为什么呢?我在struct(作为类)中有很多小方法,并且对于所有结构都发现了相同的结构,所以我想避免在每个结构(类)中复制和粘贴Discover
去游乐场https://play.golang.org/p/nYc2hc3UbG
提前致谢!
答案 0 :(得分:7)
没有。您已在A
中嵌入B
。 B
没有Discover
的定义,因此始终会调用A
上的版本。该方法具有A
类型的接收方,而A
不知道B
或B
中嵌入的事实。因此,A
只能将其称为GetTest()
的自己版本。
B
满足发现界面的唯一原因是因为它嵌入了A
。它间接地实现它。如果您想要B
上的功能,则必须在B
上进行定义。这根本不是多态性,它的组成。 B
不是A
,B
有A
。如果你想要多态,你可以使用接口并实现它们。 B
是可发现的,但仅因为它有A
。
我认为这仅仅是为了示例,但实际上你甚至没有理由拥有这个Discovery
方法。您的界面应该只需要GetTest
。不要将嵌入与继承混为一谈。 Go中没有继承。如果你想要多态行为,你可以通过实现接口来实现它,你不能像这样切角,因为嵌入式和embeddor之间的关系不是继承,没有基类或"覆盖&# 34。
答案 1 :(得分:1)
要添加到@ evanmcdonnal的观点,嵌入既不是继承也不是多态。继承恰好是一种方便,你可以免费获得一个接口的实现,但在Go中,它是显式的。正如@evanmcdonnal所指出的那样,嵌入可能看起来像是继承,但不是。
相反,您应该将概念多态与继承以及嵌入和继承分开。比较不会从大多数面向对象的语言中延续下来。作为一个例子,下面将是多态的实现。请注意Discover
接受一个接口,A
和B
实现接口,使函数本身具有多态性。
package main
import "fmt"
type A struct{}
type B struct{}
type Test interface{
GetTest() string
}
func (a *A) GetTest() string {
return "i am in A"
}
func (b *B) GetTest() string {
return "i am in B"
}
func Discover(t Test) string {
return t.GetTest()
}
func main() {
a := &A{}
b := &B{}
fmt.Println(Discover(a))
fmt.Println(Discover(b))
}