如何将一个“子”结构体传递给接受“父”结构体的函数?

7
我正在尝试在Go语言中使用继承,虽然技术上不支持继承(据我所知),但可以通过使用匿名字段来获得类似的功能。
以下是我如何定义两个结构体之间的“继承”:
//Parent struct:

type FSEntity struct {
    guid GUIDNumber
}

//Child struct:

type DataBlock struct {
    FSEntity
    data []byte
}

我现在定义了一个函数,如下所示,该函数应该接受父结构体FSEntity的实例:

Put(entity FSEntity) {....}

但是当我尝试将DataBlock的实例(该实例通过继承也是FSEntity)传递到上面的Put函数中时:

guidNumber := GUIDNumber(1234)
value := []byte("sample string")
dataBLock := DataBlock{FSEntity{guidNumber}, value}

Put(dataBLock)

在上面的最后一行,我得到了这个错误:
cannot use dataBLock (type DataBlock) as type FSEntity in argument to Put

我该如何解决这个问题?
4个回答

10

我认为你使用的术语导致了问题。在这种情况下,你只需要像这样引用内部结构:Put(dataBLock.FSEntity)

但是,为了澄清,这里没有父子关系。你正在使用一种称为嵌入的语言特征,它类似于组合(即一个类型由其他类型组成),只是你嵌入的东西具有其字段/方法被提升到嵌入作用域的功能。因此,你不能传递你所谓的“子”类型,因为这里没有多态行为,就像从一个类型继承一样,相反,你的类型是由它组成的,但你可以访问它的字段而不需要额外的间接级别。由于你的方法接受嵌入类型作为参数,所以必须明确引用它才能仅传递它。外部结构与该类型无关。


谢谢您的解释。那么在Go中我根本无法使用适当的继承吗?因为我想要的功能是,在Put()内部,我能够访问BOTH类的变量,如果我只是简单地执行Put(dataBLock.FSEntity),那将不可能实现。 - Ahmad
1
@Ahmad如果你想要访问两个结构体的变量,你需要更新Put的定义,使其参数类型为DataBlock。Go语言中没有继承,你需要以不同的方式思考问题。当语言中不存在多态概念时,你试图利用它。如果你想要那种动态行为(比如一个包含许多类型的集合,这些类型应该具有一些共同的行为/字段等),那么你可以将其抽象到接口后面。 - evanmcdonnal

2

这并不是继承的概念,而是将Put定义为方法。

func (entity FSEntity) Put() {....}

然后在嵌入后进行。
type DataBlock struct {
    FSEntity
    data []byte
}

DataBlock可以使用这个方法

dataBLock.Put()

0
package main

import (
    "fmt"
)

type Guider interface {
    Guid() string
}
type FSEntity struct {
    guid string
}
func (e FSEntity) Guid() string {
    return e.guid
}

//Child struct:

type DataBlock struct {
    FSEntity
    data []byte
}

func main() {
    myVar := DataBlock{}
    myVar.guid = "test"
    myVar.data = []byte("moar test")
    Put(myVar)
}

func Put(x Guider) {
    fmt.Printf("%+v\n", x)
}

一个接口可以帮助你接受父结构。

0
最简单的解决方法是满足参数的类型:传递一个 FSEntity。如果你只需要从嵌入它的结构体中获取 FSEntity,那么你可以直接使用 dataBlock.FSEntity
//Parent struct:

type FSEntity struct {
    guid string
}

//Child struct:

type DataBlock struct {
    FSEntity
    data []byte
}

func main() {
    myVar := DataBlock{}
    myVar.guid = "test"
    myVar.data = []byte("moar test")
    a(myVar.FSEntity)
}

func a(x FSEntity) {
    fmt.Printf("%+v\n", x)
}

(前往playground)


但我想要的功能是,在Put函数内部,我也应该能够访问“子”结构体的变量。以你的代码结构来看,我认为这是不可能的。 - Ahmad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接