基本介绍
变量(实例)具有多种形态。面向对象的第三大特征,在Go语言,多态特征是通过接口实现的(接口能够体现多态的特征)。可以按照统一的接口来调用不同的实现。这时接口变量就呈现不同的形态。
在前面的Usb接口案例,usb既可以接收手机变量,又可以接收相机变量,就体现了Usb接口多态特性。(自动的根据上下文环境来判断usb变量到底是什么类型的变量)
接口体现多态特征
1)多态参数
在前面的Usb接口案例,Usb usb即可以接收手机变量,又可以接收相机变量,就体现了Usb接口多态
2)多态数组
演示一个案例:给Usb数组中,存放Phone结构体和Camera结构体变量,Phone还有一个特有的方法call(),请遍历Usb数组,如果是Phone变量,除了调用Usb接口声明的方法外,还需要调用Phone特有方法call.
package main
import "fmt"
type Usb interface {
Working()
}
type Phone struct {
}
type Camera struct {
}
func (*Phone) Working() {
fmt.Println("phone start working......")
}
func (*Camera) Working() {
fmt.Println("camera start working......")
}
func test(usb ...Usb) {
for _, v := range usb {
v.Working()
}
}
func main() {
p := new(Phone)
c := new(Camera)
test(p, c)
}
有时候需要去做判断,去看传进来的变量具体是哪种类型,可以使用什么样的方法。这个时候就需要去使用类型断言。
这个类型也不能瞎转化,这个得空接口的的确指向的是Point类型。同时注意指=指向的是结构体变量类型还是结构体指针类型。
其实就是要将空接口转化为对应的类型,那么就会使用到类型断言。
在类型断言的时候,如果不匹配,就会报错panic,因此进行类型断言的时候要确保原来空接的类型指向的转换就是要断言的类型。这样判断避免了类型断言失败导致整个程序崩溃。
断言案例1
给Phone结构体增加一个特有的方法callo。当Usb接收的是Phone变量时,还需要调用call 方法。走代码
package main
import "fmt"
type Usb interface {
Start()
Stop()
}
type Phone struct {
}
type Camera struct {
}
type Computer struct {
}
func (*Phone) Start() {
fmt.Println("phone start work.........")
}
func (*Phone) Call() {
fmt.Println("phone call")
}
func (*Phone) Stop() {
fmt.Println("phone stop work............")
}
func (*Camera) Start() {
fmt.Println("camera start work.........")
}
func (*Camera) Stop() {
fmt.Println("camera stop work.......")
}
func (*Computer) Working(usb ...Usb) {
for _, v := range usb {
v.Start()
if p, ok := v.(*Phone); ok {
p.Call()
}
v.Stop()
}
}
func main() {
computer := new(Computer)
camera := new(Camera)
phone := new(Phone)
u := []Usb{camera, phone}
computer.Working(u...)
}
这里面有个phone结构体,它有自己独特的方法,这里使用了类型断言先去断言是否是phone,如果返回没问题就去调用结构体独有的方法。
断言一旦失败,那么ok返回的是false,那么它大不了不执行,但是并不会影响整个程序的运行,并不会Panic。
断言类型2
这样传递的参数的个数和类型都是不确定的。
items ...interface{}
package main
import "fmt"
func TypeJudge(items ...interface{}) {
for _, v := range items {
switch v.(type) {
case bool:
fmt.Println(v, "type is bool")
case int64, int:
fmt.Println(v, "type is int64")
case string:
fmt.Println(v, "type is string")
case float64:
fmt.Println(v, "type is float64")
case nil:
fmt.Println(v, "type is nil")
default:
fmt.Println(v, "type is unknown")
}
}
}
func main() {
iFace := []interface{}{1, "hello", 2.3456, true}
TypeJudge(iFace...)
}
上面可以看到不仅仅可以实现已有类型的判断还可以实现自定义类型的判断。