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项目中使用init()
Apr 12 Golang
win10下go mod配置方式
Apr 25 Golang
Golang 正则匹配效率详解
Apr 25 Golang
Go使用协程交替打印字符
Apr 29 Golang
Golang二维数组的使用方式
May 28 Golang
浅谈Golang 切片(slice)扩容机制的原理
Jun 09 Golang
Go 语言下基于Redis分布式锁的实现方式
Jun 28 Golang
golang内置函数len的小技巧
Jul 25 Golang
Go语言并发编程 sync.Once
Oct 16 Golang
golang连接MySQl使用sqlx库
Apr 14 Golang
golang的文件创建及读写操作
Apr 14 Golang
Golang实现可重入锁的示例代码
May 25 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密码生成类实例
2014/09/24 PHP
php中base64_decode与base64_encode加密解密函数实例
2014/11/24 PHP
Yii框架中jquery表单验证插件用法示例
2016/10/18 PHP
PHP strcmp()和strcasecmp()的区别实例
2016/11/05 PHP
PHP 观察者模式深入理解与应用分析
2019/09/25 PHP
js实现表单检测及表单提示的方法
2015/08/14 Javascript
js实现简洁大方的二级下拉菜单效果代码
2015/09/01 Javascript
Eclipse引入jquery报错如何解决
2015/12/01 Javascript
详解微信小程序 wx.uploadFile 的编码坑
2017/01/23 Javascript
jQuery菜单实例(全选,反选,取消)
2017/08/28 jQuery
vue 数组和对象不能直接赋值情况和解决方法(推荐)
2017/10/25 Javascript
js/jquery遍历对象和数组的方法分析【forEach,map与each方法】
2019/02/27 jQuery
JavaScript遍历数组的三种方法map、forEach与filter实例详解
2019/02/27 Javascript
nodejs分离html文件里面的js和css的方法
2019/04/09 NodeJs
让 babel webpack vue 配置文件支持智能提示的方法
2019/06/22 Javascript
学习LayUI时自研的表单参数校验框架案例分析
2019/07/29 Javascript
vue实现简单跑马灯效果
2020/05/25 Javascript
js实现盒子拖拽动画效果
2020/08/09 Javascript
js实现QQ邮箱邮件拖拽删除功能
2020/08/27 Javascript
Python中字典映射类型的学习教程
2015/08/20 Python
浅谈python jieba分词模块的基本用法
2017/11/09 Python
使用python验证代理ip是否可用的实现方法
2018/07/25 Python
Python实现随机创建电话号码的方法示例
2018/12/07 Python
pytorch 中pad函数toch.nn.functional.pad()的用法
2020/01/08 Python
Python网络爬虫信息提取mooc代码实例
2020/03/06 Python
Django正则URL匹配实现流程解析
2020/11/13 Python
python中把元组转换为namedtuple方法
2020/12/09 Python
super关键字的用法
2012/04/10 面试题
大学生职业生涯规划书前言
2014/01/09 职场文书
2014信息公开实施方案
2014/02/22 职场文书
大一学生职业生涯规划
2014/03/11 职场文书
历史学专业求职信
2014/06/19 职场文书
学校群众路线专项整治方案
2014/10/31 职场文书
2015年财务经理工作总结
2015/05/13 职场文书
浅析InnoDB索引结构
2021/04/05 MySQL
Windows server 2022创建创建林、域树、子域的步骤
2022/06/25 Servers