为了账号安全,请及时绑定邮箱和手机立即绑定

嵌入结构的覆盖行为

嵌入结构的覆盖行为

Go
幕布斯7119047 2021-08-10 13:24:31
我有一个 XY 类型,它有各种字段和方法(几十个)。type XY struct {    Name      string    SomeValue int    ...}func (xy *XY) Do1() { ... }func (xy *XY) Do2() { ... }func (xy *XY) Do3() { ... }...现在我想定义嵌入 XY 的第二种类型,保留所有字段和方法。但我确实想修改一些功能。type AB struct {    XY}func (ab *AB) Do2() { ... }到现在为止还挺好。现在我想将 AB 传递给一个接受 XY 的函数。func SomeFunc(xy *XY) { ... }这就是我绊倒的地方,没有多态性。我可以传递*AB.XY给该函数,但这将不再使用 AB 的 Do2 函数。我可以为它制作一个接口,这可能是预期的方式,但是如果 SomeFunc 需要接近 XY 的所有功能,比如几乎所有领域的 getter,我基本上需要创建 XY 的副本,作为接口(可能的用例:我在服务器上,必须以特定方式向客户端发送值)。我不想只让它成为一个接口,因为我必须重新定义使用该接口的所有类型中的所有字段和函数。我可以想到这个问题的解决方案,例如使 Do2 成为一个闭包,它是根据“主机”类型或 XY 中的枚举字段设置的,并根据该“类型”变量更改 Do2 的行为,或者使用反射和interface{}在 SomeFunc 中,但我想知道 Go 中的“正确”方式是什么。即使你有很多功能,你如何以最有效的方式做到这一点?
查看完整描述

2 回答

?
慕桂英3389331

TA贡献2036条经验 获得超8个赞

在 Go 中正确的做法是使用接口。创建的接口Do1Do2等等,使SomeFunc工作接口类型。


查看完整回答
反对 回复 2021-08-10
?
MMMHUHU

TA贡献1834条经验 获得超8个赞

就像@Ainar-G 所说的那样,使用接口是这种行为的正确方式,例如:


type Doer interface {

    Do1()

    Do2()

}


func (*S1) Do1() {

    println("S1.Do1")

}

func (*S1) Do2() {

    println("S1.Do2")

}


type S2 struct{ S1 }


func (*S2) Do1() {

    println("S2.Do1")

}


func DoIt(d Doer) {

    d.Do1()

    d.Do2()

    // you can use a type switch for specific corner cases, or implement a MarshalJson (or similar) interface for you types)

    switch v := d.(type) {

        case *S1:

            println("Special case for S1", v)

        case *S2:

            println("Special case for S2", v)


    }

}


查看完整回答
反对 回复 2021-08-10
  • 2 回答
  • 0 关注
  • 198 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信