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]\n\n", input, inputType)
}
func main() {
m1 := true
MyPrint(m1)
m2 := "Jason Yin"
MyPrint(m2)
m3 := 2020
MyPrint(m3)
}
