【玩转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】 通过组合嵌入实现代码复用的更多相关文章
- C++进阶--代码复用 继承vs组合
//############################################################################ /* * 代码复用: 继承 vs 组合 * ...
- 实验四——使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
实验目的: 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 实验过程: 查看系统调用列表 get pid 函数 #include <stdio.h> #include & ...
- go.rice 强大灵活的golang 静态资源嵌入包
以前简单介绍过packr ,statik 等静态资源嵌入工具包的使用,go.rich 是一个与packr 类似的静态资源嵌入包,使用简单 功能强大 项目结构 golang mod go mod i ...
- golang拾遗:嵌入类型
这里是golang拾遗系列的第三篇,前两篇可以点击此处链接跳转: golang拾遗:为什么我们需要泛型 golang拾遗:指针和接口 今天我们要讨论的是golang中的嵌入类型(embedding t ...
- linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...
- 在Flex (Flash)中嵌入HTML 代码或页面—Flex IFrame
在flex组件中嵌入html代码,可以利用flex iframe.这个在很多时候会用到的,有时候flex必须得这样做,如果你不这样做还真不行-- flex而且可以和html进行JavaScript交互 ...
- JSP中嵌入java代码方式以及指令
JSP中嵌入java代码的三种方式: (1)声明变量或方法 : <%! 声明; %> :慎重使用,因为此方法定义的是全局变量 (2)java片段(scriptlet): <% j ...
- 网页嵌入WMP代码(转)
网页嵌入WMP代码 播放器代码解释,装了9.0或9.0以上的播放器才能正常使用: OBJECT id="WMP" height="176" width=&quo ...
- Delphi代码中嵌入ASM代码
前言 Delphi作为一个快速高效的开发平台,使用的人越来越多,但熟悉在Delphi代码中嵌入ASM代码的程序员我想不多,因为这方面的资料太少了,另一方面,它还需要有基本的汇编语言知识,关於汇编语言的 ...
随机推荐
- JAVA-JSP内置对象之request获得所有的参数名称
相关资料:<21天学通Java Web开发> 获得所有的参数名称1.request对象的getParameterNames()方法可以获得所有的参数名称. RequestForm2.jsp ...
- 使用EGit插件将Eclipse现有项目分享到git@osc
. . . . . 程序员一定要养成使用版本管理工具的好习惯,即使是自己一个人开发的项目也要加入到版本管理工具中.使用版本管理工具主要有两个好处:一个是更好的管理多个副本,这个优势不用说了:另一个就是 ...
- EnumUtil
EnumUtil.cs using System; using System.Collections.Generic; using System.ComponentModel; using Syste ...
- 机器学习笔记,使用metrics.classification_report显示精确率,召回率,f1指数
sklearn中的classification_report函数用于显示主要分类指标的文本报告.在报告中显示每个类的精确度,召回率,F1值等信息. 主要参数: y_true:1维数组,或标签指示器数组 ...
- python 文件 IO 操作
Python 的底层操作 * 其实Python的文件IO操作方法,和Linux底层的差不多 打开 f = open(filename , "r") 后面的 "r" ...
- python json 数据操作
python 有专门针对 json 操作的函数 #!/usr/bin/python3 import json mytest_js = { "a" : 1, "b" ...
- Scrapy安装错误:Microsoft Visual C++ 14.0 is required
问题描述 当前环境win10,python_3.6.1,64位. 在windows下,在dos中运行pip install Scrapy报错: building 'twisted.test.raise ...
- Docker run 命令的使用方法
[编者的话]在Docker中,run应该是用户使用最多的命令了,很多读者反馈不是很明白run命令的用法,而且相关的书籍.中文资料中对run命令的描述也不是非常完整,所以DockerOne组织翻译了Do ...
- FileOutPutStream in 创新实训 自然语言交流系统
FileOutPutStream在c盘等一级目录下是可以创建文件的,如: new FileOutputStream("c:\\kk.txt");但是在c\\test等就创建不了,F ...
- 2、TestNG+Maven+IDEA环境搭建
前言: 主要进行TestNG测试环境的搭建 所需环境: 1.IDEA UItimate 2.JDK 3.Maven 一.创建工程 File –>new –>Project–>next ...