golang 接口嵌套实现复用的操作


Posted in Golang onApril 29, 2021

大家还是直接看代码吧~

package main
import (
    "fmt"
)
func main() {
    start(NewB(C{}))
    start(NewB(D{}))
}
type A interface {
    what()
}
type B struct {
    A
}
type C struct {
}
func (b C) what() {
    fmt.Println("this is type C")
}
type D struct {
}
func (b D) what() {
    fmt.Println("this is type D")
}
func start(b B) {
    b.what()
}
func NewB(a A) B {
    return B{a}
}

补充:【玩转Golang】通过组合嵌入实现代码复用

应用开发中的一个常见情景,为了避免简单重复,需要在基类中实现共用代码,着同样有助于后期维护。

如果在以往的支持类继承的语言中,比如c++,Java,c#等,这很简单!可是go不支持继承,只能mixin嵌入

且看下面的代码:

type ManKind interface{
    Say(s string);   
    GetMouth()string
}
type Man struct{
   
}
func NewMan() ManKind{
    return &Man{};
}
func (this *Man)GetMouth()string{
    return "M0"
}
func (this *Man) Say(s string){
    fmt.Printf("\n Speak with mouth[%s] : \"%s\"",this.GetMouth(),s);
}
type StrongMan struct{
    Man
}
func NewStrongMan()ManKind{
    return &StrongMan{}
}
func (this*StrongMan)GetMouth()string{
    return "M1"
}
func main(){    
    NewMan().Say("good luck!")
    NewStrongMan().Say("good luck!")
}

如果支持继承,很明显应该输出

Speak with mouth[M0] : "good luck!"

Speak with mouth[M1] : "good luck!"

但是在golang中只能输出:

Speak with mouth[M0] : "good luck!"

Speak with mouth[M0] : "good luck!"

StrongMan中调用Say(),此时可以将指针传递到内嵌类,只是简单的指向了Man的方法,在ManKind中调用GetMouth就是ManKind自己的GetMouth,和StrongMan没有关系。

当然,我们可以在StrongMan中覆盖Say方法

func (this *StrongMan)Say(s string){
    fmt.Printf("\n Speak with mouth[%s] : \"%s\"",this.GetMouth(),s);
}

此时,当然可以正确输出,因为本来调用的就都是StrongMan自己的方法了,这又和我们的初衷相违背了。那么这种情况怎么实现呢?我的方法是,让Man再脏一点儿,把需要的东西传递给组合进来的类。

给Man增加一个属性mouth,增加一个SetMouth方法,修改一下GetMouth方法,StrongMan的GetMouth方法删除掉,再修改一下NewStrongMan方法

最后的代码如下:

package main
import(
    "fmt"
)
type ManKind interface{
    Say(s string);    
    SetMouth(m string)
    GetMouth()string
}
type Man struct{
    ManKind    
    mouth string
}
func NewMan() ManKind{
    return &Man{mouth:"M0"};
}
func (this *Man)GetMouth()string{
    return this.mouth;
}
func (this *Man)SetMouth(s string){
    this.mouth=s;
}
func (this *Man) Say(s string){
    fmt.Printf("\n Speak with mouth[%s] : \"%s\"",this.GetMouth(),s);
}
type StrongMan struct{
    Man
}
func NewStrongMan()ManKind{
    sm := &StrongMan{}
  sm.SetMouth("M1");
  return sm;
}
    
func main(){    
    NewMan().Say("good luck!")
    &NewStrongMan().Say("good luck!")
}

当然,如果你不愿意用Get、Set方法,也可以直接输出Man的Mouth属性。

我总结的嵌入式编程要点:

1,被嵌入的类的方法,只能访问他自己的字段,包装类即时声明了同名字段也没用。

2,包装类可以覆盖嵌入类的方法,但是嵌入类访问不到,亦然访问自己的方法。只能在包装类中连同调用方法一同实现。

3,包装类覆盖嵌入类字段后,亦然可以通过嵌入类的类名访问嵌入类的字段。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Golang 相关文章推荐
Go Gin实现文件上传下载的示例代码
Apr 02 Golang
go原生库的中bytes.Buffer用法
Apr 25 Golang
Golang 实现超大文件读取的两种方法
Apr 27 Golang
浅谈Golang 嵌套 interface 的赋值问题
Apr 29 Golang
golang elasticsearch Client的使用详解
May 05 Golang
go语言中fallthrough的用法说明
May 06 Golang
Golang Gob编码(gob包的使用详解)
May 07 Golang
Golang标准库syscall详解(什么是系统调用)
May 25 Golang
Go 语言下基于Redis分布式锁的实现方式
Jun 28 Golang
Golang原生rpc(rpc服务端源码解读)
Apr 07 Golang
Golang ort 中的sortInts 方法
Apr 24 Golang
Go web入门Go pongo2模板引擎
May 20 Golang
浅谈Golang 嵌套 interface 的赋值问题
Apr 29 #Golang
Go 实现英尺和米的简单单位换算方式
Apr 29 #Golang
Golang 空map和未初始化map的注意事项说明
彻底理解golang中什么是nil
基于Go Int转string几种方式性能测试
Apr 28 #Golang
Go语言中break label与goto label的区别
golang 如何用反射reflect操作结构体
Apr 28 #Golang
You might like
WINDOWS服务器安装多套PHP的另类解决方案
2006/10/09 PHP
mysql时区问题
2008/03/26 PHP
PHP彩蛋信息介绍和阻止泄漏的方法(隐藏功能)
2014/08/06 PHP
PHP变量赋值、代入给JavaScript中的变量
2015/06/29 PHP
php 策略模式原理与应用深入理解
2019/09/25 PHP
ExtJS 2.0实用简明教程 之Border区域布局
2009/04/29 Javascript
拖动table标题实现改变td的大小(css+js代码)
2013/04/16 Javascript
js 动态修改css文件用到了cssRule
2014/08/20 Javascript
jQuery实现统计输入文字个数的方法
2015/03/11 Javascript
js实现不提交表单获取单选按钮值的方法
2015/08/21 Javascript
JavaScript中函数表达式和函数声明及函数声明与函数表达式的不同
2015/11/15 Javascript
深入理解setTimeout函数和setInterval函数
2016/05/20 Javascript
简单谈谈Vue 模板各类数据绑定
2016/09/25 Javascript
Js利用console计算代码运行时间的方法示例
2017/09/24 Javascript
AngularJS集合数据遍历显示的实例
2017/12/27 Javascript
一个Java程序猿眼中的前后端分离以及Vue.js入门(推荐)
2019/04/19 Javascript
微信小程序实现带放大效果的轮播图
2020/05/26 Javascript
Node.js 中如何收集和解析命令行参数
2021/01/08 Javascript
[03:14]2014DOTA2西雅图国际邀请赛 EG战队巡礼
2014/07/07 DOTA
[00:12]DAC SOLO赛卫冕冠军 VG.Paparazi灬展现SOLO技巧
2018/04/06 DOTA
进一步了解Python中的XML 工具
2015/04/13 Python
Python编程中运用闭包时所需要注意的一些地方
2015/05/02 Python
Python中DJANGO简单测试实例
2015/05/11 Python
python删除服务器文件代码示例
2018/02/09 Python
Python基于datetime或time模块分别获取当前时间戳的方法实例
2019/02/19 Python
python爬虫之验证码篇3-滑动验证码识别技术
2019/04/11 Python
Python对接支付宝支付自实现功能
2019/10/10 Python
Python 使用SFTP和FTP实现对服务器的文件下载功能
2020/12/17 Python
vue.js刷新当前页面的实例讲解
2020/12/29 Python
Pyside2中嵌入Matplotlib的绘图的实现
2021/02/22 Python
css3实现圆锥渐变conic-gradient效果
2020/02/12 HTML / CSS
LocalStorage记住用户和密码功能
2017/07/24 HTML / CSS
澳洲健康食品网上商店:Aussie Health Products
2018/06/15 全球购物
优秀班组申报材料
2014/12/25 职场文书
游戏《我的世界》澄清Xbox版暂无计划加入光追
2022/04/03 其他游戏
Docker部署Mysql8的实现步骤
2022/07/07 Servers