GO接口的多态性

时间:2016-05-16 17:17:51

标签: class go polymorphism

我试图在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

提前致谢!

2 个答案:

答案 0 :(得分:7)

没有。您已在A中嵌入BB没有Discover的定义,因此始终会调用A上的版本。该方法具有A类型的接收方,而A不知道BB中嵌入的事实。因此,A只能将其称为GetTest()的自己版本。

B满足发现界面的唯一原因是因为它嵌入了A。它间接地实现它。如果您想要B上的功能,则必须在B上进行定义。这根本不是多态性,它的组成。 B不是ABA。如果你想要多态,你可以使用接口并实现它们。 B是可发现的,但仅因为它有A

我认为这仅仅是为了示例,但实际上你甚至没有理由拥有这个Discovery方法。您的界面应该只需要GetTest。不要将嵌入与继承混为一谈。 Go中没有继承。如果你想要多态行为,你可以通过实现接口来实现它,你不能像这样切角,因为嵌入式和embeddor之间的关系不是继承,没有基类或"覆盖&# 34。

答案 1 :(得分:1)

要添加到@ evanmcdonnal的观点,嵌入既不是继承也不是多态。继承恰好是一种方便,你可以免费获得一个接口的实现,但在Go中,它是显式的。正如@evanmcdonnal所指出的那样,嵌入可能看起来像是继承,但不是。

相反,您应该将概念多态与继承以及嵌入和继承分开。比较不会从大多数面向对象的语言中延续下来。作为一个例子,下面将是多态的实现。请注意Discover接受一个接口,AB实现接口,使函数本身具有多态性。

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))
}