【问题标题】:go inheritance and polymorphism去继承和多态
【发布时间】:2018-04-18 20:53:18
【问题描述】:

这段代码运行不正确:

package main
import "fmt"

type Human interface {
    myStereotype() string
}

type Man struct {
}

func (m Man) myStereotype() string {
    return "I'm going fishing."
}

type Woman struct {
}

func (m Woman) myStereotype() string {
    return "I'm going shopping."
}
func main() {
    var m *Man
    m = new (Man)
    w := new (Woman)

    var hArr []*Human

    hArr = append(hArr, m)
    hArr = append(hArr, w)

    for n, _ := range (hArr) {

        fmt.Println("I'm a human, and my stereotype is: ",
                hArr[n].myStereotype())
    }
}

它存在于:

tmp/sandbox637505301/main.go:29:18: cannot use m (type *Man) as type *Human in append:
*Human is pointer to interface, not interface
tmp/sandbox637505301/main.go:30:18: cannot use w (type *Woman) as type *Human in append:
*Human is pointer to interface, not interface
tmp/sandbox637505301/main.go:36:67: hArr[n].myStereotype undefined (type *Human is pointer to interface, not interface)

但是这个运行正确(var hArr []*Human 被重写为 var hArr []Human):

package main
import "fmt"

type Human interface {
    myStereotype() string
}

type Man struct {
}

func (m Man) myStereotype() string {
    return "I'm going fishing."
}

type Woman struct {
}

func (m Woman) myStereotype() string {
    return "I'm going shopping."
}
func main() {
    var m *Man
    m = new (Man)
    w := new (Woman)

    var hArr []Human // <== !!!!!! CHANGED HERE !!!!!!

    hArr = append(hArr, m)
    hArr = append(hArr, w)

    for n, _ := range (hArr) {

        fmt.Println("I'm a human, and my stereotype is: ",
                hArr[n].myStereotype())
    }
}

输出没问题:

I'm a human, and my stereotype is:  I'm going fishing.
I'm a human, and my stereotype is:  I'm going shopping.

我不明白为什么。由于 m 和 w 是指针,为什么当我将 hArr 定义为 Human 上的指针数组时,代码会失败?

谢谢你的解释

【问题讨论】:

标签: go polymorphism


【解决方案1】:

您的主要问题是您正在使用指向接口的指针。我对this question 的回答包含有关差异的一些详细信息。可以这么说,指向接口的指针几乎总是错误的。

如果您将*Man 存储到Human(不是*Human)中,它会正常工作,因为接口可以毫无问题地存储指针。事实上,一般来说,您希望默认将指针存储在接口中,因为存储在接口中的值无法访问存储类型的指针方法。接口只是一个保存类型的存储桶,该类型是结构体还是指向结构体的指针都没有关系。另一方面,指向接口的 指针NOT 接口,并且没有与接口相同的隐式实现系统。这与无法将*func() 变量用作函数非常相似。它是一个指针,而不是一个函数。

TL;DR:不要使用指向接口的指针。它几乎从来没有用过,而且通常只是反映了对接口是什么的误解。

【讨论】:

    【解决方案2】:

    将接口视为更类似于 API 定义而不是类型可能会有所帮助。满足接口的东西已经可以是结构体或指针,所以不需要使用接口指针。如this excellent answer中所述:

    指向接口的指针几乎没有用处。事实上,Go 运行时专门更改了几个版本,不再自动取消引用接口指针(就像它对结构指针所做的那样),以阻止它们的使用。在绝大多数情况下,指向接口的指针反映了对接口应该如何工作的误解。

    【讨论】:

      猜你喜欢
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-30
      • 1970-01-01
      相关资源
      最近更新 更多