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原生库的中bytes.Buffer用法
Apr 25 Golang
golang http使用踩过的坑与填坑指南
Apr 27 Golang
Go 实现英尺和米的简单单位换算方式
Apr 29 Golang
golang slice元素去重操作
Apr 30 Golang
解决Golang中goroutine执行速度的问题
May 02 Golang
Golang之sync.Pool使用详解
May 06 Golang
Golang实现AES对称加密的过程详解
May 20 Golang
试了下Golang实现try catch的方法
Jul 01 Golang
Go并发4种方法简明讲解
Apr 06 Golang
Golang 遍历二叉树
Apr 19 Golang
Golang 入门 之url 包
May 04 Golang
GoFrame gredis缓存DoVar Conn连接对象 自动序列化GoFrame gredisDo/DoVar方法Conn连接对象自动序列化/反序列化总结
Jun 14 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
PHP实现八皇后算法
2019/05/06 PHP
php获取微信openid方法总结
2019/10/10 PHP
基于jquery的代码显示区域自动拉长效果
2011/12/07 Javascript
JQuery文字列表向上滚动的代码
2013/11/13 Javascript
Javascript call和apply区别及使用方法
2013/11/14 Javascript
使用jQuery制作Web页面遮罩层插件的实例教程
2016/05/26 Javascript
JS数组返回去重后数据的方法解析
2017/01/03 Javascript
EasyUI修改DateBox和DateTimeBox的默认日期格式示例
2017/01/18 Javascript
基于JS实现仿京东搜索栏随滑动透明度渐变效果
2017/07/10 Javascript
在vue.js中使用JSZip实现在前端解压文件的方法
2018/09/05 Javascript
使用JQuery自动完成插件Auto Complete详解
2019/06/18 jQuery
JS实现动态星空背景效果
2019/11/01 Javascript
javascript设计模式之装饰者模式
2020/01/30 Javascript
解决vue中使用less/sass及使用中遇到无效的问题
2020/10/24 Javascript
Python单链表的简单实现方法
2014/09/23 Python
python开发简易版在线音乐播放器
2017/03/03 Python
Python实现的购物车功能示例
2018/02/11 Python
Python实现的拉格朗日插值法示例
2019/01/08 Python
python 监听salt job状态,并任务数据推送到redis中的方法
2019/01/14 Python
Django项目使用CircleCI的方法示例
2019/07/14 Python
在OpenCV里使用特征匹配和单映射变换的代码详解
2019/10/23 Python
解决python web项目意外关闭,但占用端口的问题
2019/12/17 Python
python实现小程序推送页面收录脚本
2020/04/20 Python
Python应用实现双指数函数及拟合代码实例
2020/06/19 Python
plt.figure()参数使用详解及运行演示
2021/01/08 Python
美国老牌主机服务商:iPage
2016/07/22 全球购物
西铁城美国官方网站:Citizen Watch美国
2019/11/08 全球购物
PHP高级工程师面试问题推荐
2013/01/18 面试题
学生实习介绍信
2014/01/15 职场文书
安全协议书
2014/04/23 职场文书
课外活动实习计划
2015/01/19 职场文书
结婚通知短信怎么写
2015/04/17 职场文书
刑事上诉状范文
2015/05/22 职场文书
小学生读书笔记
2015/07/01 职场文书
win11无法添加打印机怎么办? 提示windows无法打开添加打印机的解决办法
2022/04/05 数码科技
Win10服务全部禁用了怎么启动?Win10服务全部禁用解决方法
2022/09/23 数码科技