第17节 多态和类型断言

59 阅读2分钟

1. 什么是多态

Go中的多态是通过接口来实现的,即可按照统一的接口来调用不同的实现,这时的接口变量就有不同的行为状态。

掘金-第 9 页.drawio.png

比如现在的Type-C数据线,它就是多态的一种体现。一个数据线可以充电脑、可以充手机,Type-C生产商已经做好了统一规范,比如支持充多少瓦的电源、支持充哪些设备等等。用代码来模拟这一场景:

package main

import "fmt"

// Type-C 接口
type TypecInterface interface {
	// 充电
	recharge()
}

type Phone struct {
	// 手机型号
	Model string
}

// 让手机 Phone 实现充电接口
func (p Phone) recharge() {
	fmt.Println("正在给手机充电中...")
}

type Macbook struct {
	// 电脑尺寸
	Size string	
}

// 让电脑 Macbook 实现充电接口
func (mac Macbook) recharge() {
	fmt.Println("正在给电脑充电中...")
}

// 充电插头
type ChargingPlug struct {
}

// 利用充电插头 + type-c 数据线进行充电操作
func (plug *ChargingPlug)working(typec TypecInterface) {
	typec.recharge()
}

func main() {
	phone := Phone{}
	mac := Macbook{}

	plug := ChargingPlug{}
	// 给手机充电
	plug.working(phone)
	// 给电脑充电
	plug.working(mac)
}

image.png

2. 类型断言

由于接口不知道具体的数据类型,如果要转成具体类型,就需要使用类型断言。类似Java中的 instanceof关键字。

package main

import "fmt"

type Point struct {
	x int
	y int
}

func main() {

	var a interface{}
	var point Point = Point{2, 3}
	a = point  // 空接口可以接受任意类型数据
        
	// a的数据类型 main.Point, 值是={2 3}
	fmt.Printf("a的数据类型 %T, 值是=%v\n", a, a)
}

那么在 Go 中能否直接执行👇🏻的代码呢?不能,会直接编译报错

var a interface{}
var b Point
// cannot use a (variable of type interface{}) as type Point in assignment: need type assertion
b = a

那么如何把一个接口变量,赋值给自定义类型的变量。此时要用到类型断言来解决该问题

package main

import "fmt"

func main() {
	// 空接口类型变量
	var x interface{}

	var b string = "assert"
	x = b // 空接口可以接受任意类型数据

	// 类型断言
	c := x.(string)
	// b的数据类型 string, 值是=assert
	fmt.Printf("b的数据类型 %T, 值是=%v\n", c, c)

	// 类型断言检测机制
	if y, result := x.(string); result {
		fmt.Println("断言判断成功...", y)
	} else {
		fmt.Println("断言判断失败...")
	}
}