前言
在之前的文章中我们说过,golang 是通过 结构体(struct)-方法(method)-接口(interface)
的组合使用来实现面向对象的思想。在前文 Golang 复合类型 和 Golang method 方法详解 已经详细介绍过 struct
和 method
,本文将介绍 golang 面向对象的另一个重要组成部分:接口(interface)
。
接口
接口概念
接口是一种抽象的类型,描述了一系列方法的集合,作用是对一系列具有联系的方法做出抽象和概括。接口只定义方法名和参数,而不包含具体的实现,这种抽象的方式可以让程序变得更加灵活更加通用。
在很多语言中,接口都是侵入式
的,侵入式接口的意思是实现类需要明确声明自己实现了某个接口,这就带来了一个很矛盾的问题,比如 A 调用了 B 的接口,那么 A 一定会希望接口被设计成自己想要使用的样子,但是 B 才是接口的实现方,基于模块设计的单向依赖原则,B 在实现自身的业务时,不应该关心某个具体使用方的要求,一个接口被定义的时候,并不知道自己的方法会被谁实现,也不知道会被怎么样实现。因此,侵入式接口一直是面向对象编程中一个经常遭受质疑的特性。
不同的是,golang 的接口是一种 非侵入式
的接口,一个类型不需要明确声明,只要实现了接口的所有方法,这个类型就实现了该接口,这个类型的对象就是这个接口类型的实例。 因此,在 golang 中,不再需要定义类的继承关系,而且在定义接口时候,只需要关心自己需要提供哪些方法,其他的方法有使用方按需定义即可。
接口定义
/* 定义接口 */
type interface_name interface {
method_name1(input_paras...) [return_type]
method_name2(input_paras...) [return_type]
method_name3(input_paras...) [return_type]
}
/* 定义结构体 */
type struct_name struct {
/* variables */
}
/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1(input_paras...) [return_type] {
/* 方法实现 */
}
func (struct_name_variable struct_name) method_name2(input_paras...) [return_type] {
/* 方法实现*/
}
func (struct_name_variable struct_name) method_name3(input_paras...) [return_type] {
/* 方法实现*/
}
go语言的源码中大量使用到了接口,比如说在前面的文章中多次使用到的 error 类型
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
Error() string
}
封装性
接口是 golang 封装性的重要一环,接口可以封装具体类型和类型的值,即使一个类型还有别的方法,接口的实例也只能调用接口暴露出来的方法。如下:
type HelloInterface interface {
Hello()
}
type User struct {
}
func (f *User) Hello() {
fmt.Println("hello")
}
func (f *User) Bye() {
fmt.Println("bye")
}
func InterfaceTest() {
u := &User{
}
u.Hello() // ok
u.Bye()