当前位置: 首页 > news >正文

go结构体匿名“继承“方法冲突时继承优先顺序

在这里插入图片描述

在 Go 语言中,匿名字段(也称为嵌入字段)可以用来实现继承的效果。当你在一个结构体中匿名嵌入另一个结构体时,嵌入结构体的方法会被提升到外部结构体中。这意味着你可以直接通过外部结构体调用嵌入结构体的方法。

如果多个嵌入结构体实现了同一个接口方法,那么调用时会根据方法的定义顺序来决定调用哪个方法。具体来说,Go 语言会选择第一个定义的方法。

示例

在这里插入图片描述

假设我们有两个结构体 AB,它们都实现了同一个接口 MyInterface,然后我们在结构体 C 中匿名嵌入了这两个结构体。

package mainimport "fmt"// MyInterface 接口
type MyInterface interface {DoSomething()
}// 结构体 A
type A struct{}func (a A) DoSomething() {fmt.Println("A.DoSomething()")
}// 结构体 B
type B struct{}func (b B) DoSomething() {fmt.Println("B.DoSomething()")
}// 结构体 C 匿名嵌入了 A 和 B
type C struct {AB
}func main() {c := C{}var myInterface MyInterface = cmyInterface.DoSomething() // 输出什么?
}

输出结果

在这个例子中,调用 myInterface.DoSomething() 会输出:

A.DoSomething()

解释

在这里插入图片描述

  • 方法提升:当 C 结构体匿名嵌入了 AB 时,AB 的方法都被提升到了 C 中。
  • 方法冲突:由于 AB 都实现了 DoSomething 方法,因此 C 中会有两个同名的方法。
  • 方法选择:在 Go 语言中,当多个嵌入字段中有同名方法时,会优先选择第一个定义的方法。在这个例子中,A 是第一个被嵌入的字段,因此 ADoSomething 方法会被调用。

更多示例

为了进一步说明这一点,我们可以添加更多的嵌入字段来观察方法的选择顺序。

package mainimport "fmt"// MyInterface 接口
type MyInterface interface {DoSomething()
}// 结构体 A
type A struct{}func (a A) DoSomething() {fmt.Println("A.DoSomething()")
}// 结构体 B
type B struct{}func (b B) DoSomething() {fmt.Println("B.DoSomething()")
}// 结构体 D
type D struct{}func (d D) DoSomething() {fmt.Println("D.DoSomething()")
}// 结构体 C 匿名嵌入了 A、B 和 D
type C struct {ABD
}func main() {c := C{}var myInterface MyInterface = cmyInterface.DoSomething() // 输出什么?
}

输出结果

在这个例子中,调用 myInterface.DoSomething() 会输出:

A.DoSomething()

解释

  • 方法提升ABDDoSomething 方法都被提升到了 C 中。
  • 方法选择:由于 A 是第一个被嵌入的字段,因此 ADoSomething 方法会被优先调用。

扩展

当继承类本身也实现了对应方法时,优先使用本身实现的方法


// MyInterface 接口
type MyInterface interface {DoSomething() string
}// 结构体 A
type A struct{}func (a A) DoSomething() string {fmt.Println("A.DoSomething()")return "A"
}// 结构体 B
type B struct{}func (b B) DoSomething() string {fmt.Println("B.DoSomething()")return "B"
}// 结构体 C 匿名嵌入了 A 和 B
type C struct {AB
}func (c C) DoSomething() string {fmt.Println("C.DoSomething()")return "C"
}func TestEnhanceStrcutC(t *testing.T) {var baseC C// 这里将会调用func (c C) DoSomething() stringif "C" != baseC.DoSomething() {t.Error("DoSomething failed.")}
}

总结

在 Go 语言中,当一个结构体匿名嵌入了多个实现相同接口的结构体时,调用该接口方法时会优先选择自己实现的方法,如果自己没有实现该方法,就按照顺序从上到下找到第一个定义的方法。方法的定义顺序决定了调用哪个方法。但是为了避免歧义和提高代码的可读性,建议在设计时尽量避免这种情况,或者在外部结构体中显式地实现接口方法。

http://www.lryc.cn/news/493855.html

相关文章:

  • 【049】基于51单片机语音录放【Proteus仿真+Keil程序+报告+原理图】
  • 《软件项目管理》期末-复习题及参考答案
  • milvus 通俗易懂原理
  • 什么是撞库、拖库和洗库?
  • 安卓-碎片的使用入门
  • 华为IPD流程学习之——深入解读123页华为IPD流程体系设计方法论PPT
  • DriveMLLM:一个专为自动驾驶空间理解任务设计的大规模基准数据集
  • 高效处理 iOS 应用中的大规模礼物数据:以直播项目为例(1-礼物池)
  • python的函数与递归
  • RabbitMQ学习-Seven
  • 中科亿海微SoM模组——波控处理软硬一体解决方案
  • 开源法律、政策和实践
  • 【计算视觉算法与应用】金字塔,下采样Gaussian Pyramid. 上采用 Laplacian Pyramid (code: py)
  • 基于BERT的语义分析实现
  • DNS查询工具
  • ODB 框架
  • Ubuntu WiFi检测
  • QILSTE H4-108TCG高亮纯lu光LED灯珠 发光二极管LED
  • IP与“谷子”齐飞,阅文“乘势而上”?
  • Java阶段三05
  • C# yield 关键字
  • SpringBoot开发——结合Nginx实现负载均衡
  • RabbitMQ在手动消费的模式下设置失败重新投递策略
  • TsingtaoAI具身智能高校实训方案通过华为昇腾技术认证
  • 【Linux】线程池设计 + 策略模式
  • 网络原理(一):应用层自定义协议的信息组织格式 HTTP 前置知识
  • Python-链表数据结构学习(1)
  • 性能优化经验:关闭 SWAP 分区
  • SpringBoot小知识(2):日志
  • java虚拟机——jvm是怎么去找垃圾对象的