Class GO接口中的多态性

Class GO接口中的多态性,class,go,polymorphism,Class,Go,Polymorphism,我试图在围棋中达到这种多态性 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() st

我试图在围棋中达到这种多态性

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 as类中使用了很多小方法,发现所有结构都是一样的,所以我希望避免在每个struct类中复制粘贴发现

去操场

提前谢谢

否。您将A嵌入到B中。B没有发现的定义,因此始终调用A上的版本。该方法有一个类型为a的接收器,而a不知道B或它嵌入B中的事实。因此a只能调用它自己的GetTest版本

B满足discover接口的唯一原因是因为它有一个嵌入式接口。它间接地实现了它。如果你想在B上定义功能,你必须在B上定义它。这根本不是多态性,而是组合。B不是A,B有A。如果需要多态性,可以使用接口并实现它们。B是可发现的,但只是因为它有a

我假设这只是一个示例,但实际上您根本没有理由使用这种发现方法。您的接口应该只需要GetTest。不要混淆嵌入和继承。围棋没有继承权。如果您想要多态行为,您可以通过实现接口来实现它,并且您不能像这样走捷径,因为嵌入类型和嵌入程序之间的关系不是继承关系,没有基类或重写。

否。您将A嵌入B。B没有发现的定义,因此,始终调用上的版本。该方法有一个类型为a的接收器,而a不知道B或它嵌入B中的事实。因此a只能调用它自己的GetTest版本

B满足discover接口的唯一原因是因为它有一个嵌入式接口。它间接地实现了它。如果你想在B上定义功能,你必须在B上定义它。这根本不是多态性,而是组合。B不是A,B有A。如果需要多态性,可以使用接口并实现它们。B是可发现的,但只是因为它有a


我假设这只是一个示例,但实际上您根本没有理由使用这种发现方法。您的接口应该只需要GetTest。不要混淆嵌入和继承。围棋没有继承权。如果您想要多态行为,您可以通过实现接口来实现它,并且您不能像这样走捷径,因为嵌入类型和嵌入程序之间的关系不是继承关系,没有基类或重写。

要补充@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))
}

要补充@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))
}

Go中没有遗传和多态性。某些相关/可能的重复项:,。Go中没有继承和多态性。一些相关的/可能的重复项:,,好的,这就是我试图实现的,也许你能告诉我如何在围棋中做到这一点?它是一个类工厂,返回的对象取决于用户输入的配置文件,然后我必须填充结构myStruct并将其保存到数据库中。好的,这就是我试图实现的,也许你们可以告诉我如何在GO中实现它?它是类工厂,返回的对象实际上取决于用户输入配置文件,然后我必须填充结构myStruct并将其保存到数据库中。请在@evanmcdonnal answer中查找注释,这是我尝试做的示例。我会避免在代码中使用诸如BaseClass和DerivedClass之类的名称。由于Go中没有类和继承这样的东西,这使得它更加混乱。如果你破坏了你的装置
通过使用不同的GetValue方法,您可以用它们组成一个更大的结构。这将是一种可以模拟您所需行为的方法。请在@evanmcdonnal answer中查找注释,这是我尝试做的示例。我将避免在代码中使用诸如BaseClass和DerivedClass之类的名称。由于Go中没有类和继承这样的东西,这使得它更加混乱。如果您中断了不同GetValue方法的实现,您可以用它们组成一个更大的结构。这将是一种可以模仿你想要的行为的方法。