Golang的面向接口编程
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
之前我们分享了Go语言中的面向对象的封装和继承相关知识,今天我们来了解一下Go语言如何实现多态。
一.接口概述
Go语言的接口类型用于定义一组行为,其中每个行为都由一个方法声明表示。
接口类型中的方法声明只有方法签名而没有方法体,而方法签名包括且仅包括方法的名称,参数列表和结果返回列表。
在Go语言中,接口是一个自定义类型,它声明了一个或者多个方法签名。接口是完全抽象的,因此不能将其实例化。然而,可以创建一个其类型为接口的变量,它可以被赋值为任何满足该接口类型的实际类型的值。
二.计算器案例(多态案例)
package main import ( "fmt" ) //实现面向对象版本包含加减法的计算器 type Parents struct { x int y int } //实现加法类 type Addition struct { Parents } //实现减法类 type Subtraction struct { Parents } //实现乘法类 type multiplication struct { Parents } //实现除法类 type Division struct { Parents } func (this *Addition) Operation() int { return this.x + this.y } func (this *Subtraction) Operation() int { return this.x - this.y } func (this *multiplication) Operation() int { return this.x * this.y } func (this *Division) Operation() int { return this.x / this.y } /** 实现接口版本包含加减法的计算器 接口就是一种规范标准,接口中不做函数实现,只做定义函数格式 面向接口编程(也称为面向协议编程)降低了代码的耦合度,方便后期代码的维护和扩充,这种实现方法我们称之为多态。 多态三要素: 1>.父类是接口; 2>.子类实现所有的接口中定义的函数; 3>.有一个父类接口对应子类对象指针; */ type MyCalculator interface { Operation() int //实现接口的结构体中必须包含Operation函数名且返回值为int类型 } func Calculation(c MyCalculator) int { return c.Operation() } func main() { //调用加法 a := Addition{Parents{100, 20}} sum := a.Operation() fmt.Println(sum) //调用减法 b := Subtraction{Parents{100, 20}} sub := b.Operation() fmt.Println(sub) //调用乘法 c := multiplication{Parents{100, 20}} mul := c.Operation() fmt.Println(mul) //调用除法 d := Division{Parents{100, 20}} div := d.Operation() fmt.Println(div) fmt.Println("===== 我是分割线 =====") //调用接口,需要传入对象指针,相比上面面向对象的方法来说,接口表现了面向接口三要素中的多态特征。 fmt.Println(Calculation(&a)) fmt.Println(Calculation(&b)) fmt.Println(Calculation(&c)) fmt.Println(Calculation(&d)) }
三.空接口和类型断言案例
package main import ( "fmt" "reflect" ) /** 空接口(interface{})不包含任何的方法,正因为如此,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值。 如下所示,我们为空接口起了一个别名. */ type MyInterface interface{} func MyPrint(input MyInterface) { /** 使用断言语法获取传输过来的数据类型,类似于类型强转。 断言语法格式如下: 接口类型变量.(断言的类型) 如果你不确定interface具体是什么类型,那么再断言之前最好先做判断。 */ output, ok := input.(int) if ok { output = input.(int) + 100 //通过断言语法可以判断数据类型 fmt.Println(output) } else { fmt.Println(input) } inputType := reflect.TypeOf(input) //通过反射也可以判断类型 fmt.Printf("用户传入的是:[%v],其对应的类型是[%v] ", input, inputType) } func main() { m1 := true MyPrint(m1) m2 := "Jason Yin" MyPrint(m2) m3 := 2020 MyPrint(m3) }