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语言使用select{}阻塞main函数介绍
Apr 25 Golang
go语言-在mac下brew升级golang
Apr 25 Golang
Go语言中的UTF-8实现
Apr 26 Golang
golang中切片copy复制和等号复制的区别介绍
Apr 27 Golang
基于Go Int转string几种方式性能测试
Apr 28 Golang
Go语言实现一个简单的并发聊天室的项目实战
Mar 18 Golang
简单聊聊Golang中defer预计算参数
Mar 25 Golang
如何解决goland,idea全局搜索快捷键失效问题
Apr 03 Golang
Go归并排序算法的实现方法
Apr 06 Golang
Golang ort 中的sortInts 方法
Apr 24 Golang
Python测试框架pytest核心库pluggy详解
Aug 05 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网页后退不再出现过期
2007/03/08 PHP
PHP 输出缓存详解
2009/06/20 PHP
JCalendar 日历控件 v1.0 beta[兼容IE&Firefox] 有文档和例子
2007/05/30 Javascript
ExtJS 2.0实用简明教程 之获得ExtJS
2009/04/29 Javascript
jQuery中的bind绑定事件与文本框改变事件的临时解决方法
2010/08/13 Javascript
jquery简单实现滚动条下拉DIV固定在头部不动
2013/11/25 Javascript
jquery 提示信息显示后自动消失的具体实现
2013/12/18 Javascript
Chrome下ifame父窗口调用子窗口的问题示例探讨
2014/03/17 Javascript
javascript在网页中实现读取剪贴板粘贴截图功能
2014/06/07 Javascript
纯JS实现图片验证码功能并兼容IE6-8(推荐)
2017/04/19 Javascript
微信小程序 flex实现导航实例详解
2017/04/26 Javascript
在 Angular 中使用Chart.js 和 ng2-charts的示例代码
2017/08/17 Javascript
Js判断H5上下滑动方向及滑动到顶部和底部判断的示例代码
2017/11/15 Javascript
Javascript删除数组里的某个元素
2019/02/28 Javascript
MockJs结合json-server模拟后台数据
2020/08/26 Javascript
Python中的推导式使用详解
2015/06/03 Python
python中 logging的使用详解
2017/10/25 Python
python实现画五角星和螺旋线的示例
2019/01/20 Python
动态设置django的model field的默认值操作步骤
2020/03/30 Python
python操作链表的示例代码
2020/09/27 Python
python subprocess pipe 实时输出日志的操作
2020/12/05 Python
倩碧美国官网:Clinique美国
2016/07/20 全球购物
方法名是否可以与构造器的名字相同
2012/06/04 面试题
三年大学生活自我鉴定
2014/01/21 职场文书
50岁生日感言
2014/01/23 职场文书
地球一小时宣传标语
2014/06/24 职场文书
交警作风整顿剖析材料
2014/10/11 职场文书
2014年维修工作总结
2014/11/22 职场文书
2014年移动公司工作总结
2014/12/08 职场文书
特此通知格式
2015/04/27 职场文书
文化大革命观后感
2015/06/17 职场文书
大学班长竞选稿
2015/11/20 职场文书
离婚协议书范文2016
2016/03/18 职场文书
Spring Bean的实例化之属性注入源码剖析过程
2021/06/13 Java/Android
python中Pyqt5使用Qlabel标签播放视频
2022/04/22 Python
Vue 打包后相对路径的引用问题
2022/06/05 Vue.js