Go语言的接口interface、struct和组合、继承

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也没有继承这种功能。blog

上面的代码并无说明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类型对象。运行结果以下:seo

I'm der1
I'm der2

 

Go中没有继承的功能,它是经过接口来实现相似功能,Go中还有一种叫作组合的概念,以下:class

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的方法,由于其不是继承,因此不会根据具体传入的对象而执行对应的方法。import

 

下面的的代码又说明了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( )方法。

相关文章
相关标签/搜索