Go语言的interface概念相对于C++中的基类,通过interface来实现多态功能。

在C++中,当需要实现多态功能时,步骤是首先定义一个基类,该基类使用虚函数或者纯虚函数抽象了所有子类会用到的共同的最基本的成员函数,之后子类继承该基类,然后每个派生类自定义自己的虚函数实现。最后在使用基类指针或者引用的地方传入派生类,程序根据具体传入的对象来调用对象的函数。

在Go中,定义一个interface类型,该类型说明了它有哪些方法,这就完成了类似C++中的基类定义,然后在其他的函数中,将该interface类型作为函数的形参,任意一个实现了interface类型的实参都能作为该interface的实例对象。interface类型和作为interface类型的实参对象之间就相当于存在继承关系,或者说叫实现接口(Java说法),但这种继承关系(实现接口)是隐式的(自动的),也即我们无需主动说明(显式implements实现)该实参类型是某interface类型的派生类,代码如下:

type base interface { //类似基类定义
virtualfunc() int //类似虚函数抽象定义
} type der1 int //类似派生类1定义 func (der1) virtualfunc() int { //类似派生类1虚函数具体实现
fmt.Printf("I'm der1\n")
return 1
} type der2 struct { //类似派生类2定义
//nothing
} func (der2) virtualfunc() int { //类似派生类2虚函数具体实现
fmt.Printf("I'm der2\n")
return 2
} func somefunc(b base) { //作为某个函数的形参
b.virtualfunc()
}

上述代码中base是interface类型,b作为somefunc( )函数的形参,因为base接口类型要求实现virtualfunc( )函数,而der1和der2都实现了该函数,因为der1和der2自动是base的派生类,在somefunc( )函数中,要求base类型的实参时,可以用der1或者der2的实例对象传入,这就实现了不同类型不同行为,也即多态。这是Go实现面向对象特性的一种特殊方法,并不是通过类和继承来完成的,Go也没有继承这种功能。

上面的代码并没有说明interface的全部特性,还有一些说明如下:

  1. 实现某个接口的类型(如上面的der2)可以有其他的方法。这正如派生类还可以额外增加基类并没有的成员函数一样,但增加的函数不是接口中的部分。
  2. 一个类型可以实现多个接口。这类似于C++的多继承,一个派生类可以当做多种基类来使用。

从somefunc( )函数中的形实参结合可以看到,我们能定义一个interface类型的变量,并用一个“派生类”去初始化或者赋值,代码如下:

func main() {
var baseobj base var d1 der1
baseobj = d1
somefunc(baseobj) var d2 der2
baseobj = d2
somefunc(baseobj)
}

上面代码中,第2行是定义了一个默认初始化的interface base类型对象,第5行和第9行代码则是用两个“派生类”去赋值interface base类型对象。运行结果如下:

I'm der1
I'm der2

Go中没有继承的功能,它是通过接口来实现类似功能,Go中还有一种叫做组合的概念,如下:

package main

import (
"fmt"
) type Base struct {
// nothing
} func (b *Base) ShowA() {
fmt.Println("showA")
b.ShowB()
}
func (b *Base) ShowB() {
fmt.Println("showB")
} type Derived struct {
Base
} func (d *Derived) ShowB() {
fmt.Println("Derived showB")
} func main() {
d := Derived{}
d.ShowA()
}

上述代码执行结果不会输出“Derived showB”,因为Go中没有继承的概念,只有组合,上面的Derived包含了Base,自动的含有了Base的方法,因为其不是继承,所以不会根据具体传入的对象而执行对应的方法。

下面的的代码又说明了type name和type struct的区别:

package main

import (
"fmt"
) type Mutex struct {
// nothing
} func (m *Mutex) Lock() {
fmt.Println("mutex lock")
} func (m *Mutex) Unlock() {
fmt.Println("mutex unlock")
} type newMutex Mutex type structMutex struct {
Mutex
} func main() {
m1 := Mutex{}
m1.Lock() // n1 := newMutex{}
// n1.Lock() 没有Lock()方法 x1 := structMutex{}
x1.Lock() }

上面的代码中n1不能执行Lock( )函数,因为Golang不支持隐式类型转换,虽然newMutex就是Mutex,但语法上它们是两种类型,因此newMutex不能执行Lock( )方法。

Go语言的接口interface、struct和组合、继承的更多相关文章

  1. Ts中的接口interface(属性也能继承...)

    接口ITest.ts interface ITest { name:string; age:number; run(); to(x:number,y:number):number; } 必须继承接口的 ...

  2. Go语言学习笔记(四)结构体struct & 接口Interface & 反射

    加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struc ...

  3. Go语言学习笔记(四)结构体struct & 接口Interface & 反射reflect

    加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struc ...

  4. go语言中的接口interface

    package main; import "fmt" //接口interface //接口是一个或多个方法签名的集合 //只要某个类型拥有该接口的所有方法签名,即算实现该接口. / ...

  5. FFI (语言交互接口(Foreign Function Interface))

    FFI(Foreign Function Interface)是用来与其它语言交互的接口, 在有些语言里面称为语言绑定(language bindings), Java 里面一般称为 JNI(Java ...

  6. 【Golang】Go 通过结构(struct) 实现接口(interface)

    一.通过结构(struct) 实现 接口(interface) 1.在了解iris框架的时候,经常看到有这样去写的使用一个空结构体作为接收器,来调用方法,有点好奇这样做有什么意义. 解释:在 Go 语 ...

  7. Go接口interface

    目录 接口是什么? interface类型 空接口(interface{}) interface函数参数 interface变量存储的类型 类型断言 嵌入interface 接口是什么? Go 语言不 ...

  8. Go 接口(interface)

        文章转载地址:https://www.flysnow.org/2017/04/03/go-in-action-go-interface.html 1.什么是 interface? 简单的说,i ...

  9. 深度解密Go语言之关于 interface 的10个问题

    目录 1. Go 语言与鸭子类型的关系 2. 值接收者和指针接收者的区别 方法 值接收者和指针接收者 两者分别在何时使用 3. iface 和 eface 的区别是什么 4. 接口的动态类型和动态值 ...

随机推荐

  1. php手册 | python手册 | perl手册 | c#.net手册 | c++手册 | ruby手册 | jquery手册 | js手册 | prototype手册 | mysql手册 | smarty手册 | css手册 | html手册 | nginx手册 | apache手册 | shell手册 | svn手册

    收集各种实用类手册: http://shouce.jb51.net/shell/

  2. Nagios通过企业微信报警

    主要分两部分进行: 注册企业微信,自建应用,获取与发送消息相关的信息: 编写调用微信API脚本(bash),配置Nagios微信报警: 一.企业微信 1.注册企业微信:https://work.wei ...

  3. Alpha 冲刺 —— 十分之六

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 测试服务器并行能力 学习MSI.CUDA ...

  4. P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold 解题报告

    P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold 题意 给一个字符串,每次可以从两边中的一边取一个字符,要求取出的字符串字典序最小 可以Hash+二分 也可以S ...

  5. 【纪中集训2019.3.23】IOer

    题目 描述 你要在\(m\)天内,刷\(n\)道题,每天可以刷的题的数目不限: 第\(i\)天可以刷的题目的种类是\(ui+v\): 两种刷题的方案不同当且仅当某天刷题的数量不同或者依次刷题的种类不同 ...

  6. 如何修改Windows程序的权限?

    修改程序的权限需要用到3个函数: 1. 获取进程的令牌句柄: OpenProcessToken 2. 查找特权类型的ID: LookupPrivilegeValue 3. 修改进程的特权:Adjust ...

  7. 初识Unity Mesh

    Mesh概念:Mesh是Unity中的一个组件,称为网格组件.通俗的讲,Mesh是指模型的网格,3D模型是由多边形拼接而成,而多边形实际上是由多个三角形拼接而成的.所以一个3D模型的表面其实是由多个彼 ...

  8. ribbion的负载均衡之端口的切换

    可以说在这里被坑了很久,终于今天在大神的指导下,成功实现了负载均衡,切换不同的端口,这里来记录下,首先来看下效果图吧: 到底是怎么实现的呢?到底是如何切换的呢? 具体来讲: 几个步骤,启动服务注册中心 ...

  9. HAOI2018游记

    前言 很懒. 太懒了. 不仅懒得写题..连游记都懒得写.. 花点时间填一下坑吧..不过话说我去年的NOI/APIO/CTSC游记也没写.. 省选前 板子好像一早就打完了,没什么可干的. 也不愿意开新题 ...

  10. poj 2396 Budget

    一个m行n列的矩阵,给出每行每列中元素的和,以及对一些格子的大小限制,求一个可行方案,输出矩阵. 大小限制形如:严格大于i,严格小于i,等于i. 1<=m<=200.1<=n< ...