Golang 通用万能类型 interface 接口与类型断言
2022-4-13 16:44:8 Author: mp.weixin.qq.com(查看原文) 阅读量:6 收藏

0x00 多态的实现

在聊通用万能类型 interface{} 接口之前,先来谈谈 Golang 中多态的实现与基本要素。

interface 定义抽象方法,子类继承并且实现对应的抽象方法,以达到一个抽象接口有多个不同表现形式的目的,这种现象被称为面向对象的多态。

当我们继承一个类时,需要在 struct 中将父类的名字写下来,如果继承接口的话,则无需将父类的名字写下来,直接将接口包含的抽象方法全部实现即可,此时我们可以直接使用 interface 指针接收(指向)一个子对象。

package main

import "fmt"

// 本质是一个指针
type AnimalIF interface {
 Sleep()
 GetColor() string // 获取动物的颜色
 GetType() string  // 获取动物的种类
}

// 具体的类
type Cat struct {
 color string // 猫的颜色
}

func (this *Cat) Sleep() {
 fmt.Println("Cat is Sleep...")
}

func (this *Cat) GetColor() string {
 return this.color
}

func (this *Cat) GetType() string {
 return "Cat"
}

type Dog struct {
 color string
}

func (this *Dog) Sleep() {
 fmt.Println("Dog is Sleep...")
}

func (this *Dog) GetColor() string {
 return this.color
}

func (this *Dog) GetType() string {
 return "Dog"
}

func showAnimal(animal AnimalIF) {
 animal.Sleep() // 多态
 fmt.Println("color = ", animal.GetColor())
 fmt.Println("kind = ", animal.GetType())
}

func main() {
 var animal AnimalIF // 接口的数据类型,父类指针
 animal = &Cat{"Green"}
 animal.Sleep() // 调用的就是 Cat 的 Sleep() 方法

 animal = &Dog{"Yellow"}
 animal.Sleep() // 调用 Dog 的 Sleep() 方法,多态现象

 cat := Cat{"Green"}
 dog := Dog{"Yellow"}

 showAnimal(&cat)
 showAnimal(&dog)
}

go fmt .\main.go
go run .\main.go
image
image

0x01 多态的基本要素

  1. 有一个父类(有接口)
  2. 有子类(实现了父类的全部接口方法)
  3. 父类类型的变量(指针)指向(引用)子类的具体数据变量

0x02 通用万能类型 interface{}

通用万能类型 interface{},就是元类,表示空接口,就是所有的 struct 最终都实现了这个空接口。

如 int、string、float32、float64、struct 都实现了 interface{} 空接口,可以使用 interface{} 数据类型引用任意数据类型。

package main

import "fmt"

func myFunc(arg interface{}) {
 fmt.Println("myFunc() is called...")
 fmt.Println(arg)
}

type Book struct {
 auth string
}

func main() {
 book := Book{"Golang"}
 myFunc(book)
 myFunc(233)
 myFunc("tonghuaroot")
 myFunc(3.14)
}

image

0x03 类型断言

通过类型断言机制,interface{} 可以区分引用的底层数据类型。

package main

import "fmt"

func myFunc(arg interface{}) {
 fmt.Println("myFunc() is called...")
 fmt.Println(arg)

 value, ok := arg.(string)
 if !ok {
  fmt.Println("==========")
  fmt.Println("arg is not string type")
  fmt.Println("value = ", value)
  fmt.Printf("value type is %T \n", value) // 在类型断言机制中,如果 arg 不是 string 类型,则 value 值为一个 string 类型的空值(其他类型也适用)
  fmt.Println("==========")
 } else {
  fmt.Println("arg is string type, value = ", value)
  fmt.Printf("value type is %T \n", value)
 }
}

type Book struct {
 auth string
}

func main() {
 book := Book{"Golang"}
 myFunc(book)
 myFunc(233)
 myFunc("tonghuaroot")
 myFunc(3.14)
}

image

0x04 相关疑问

  1. 似乎父类子类之间的继承与接口(抽象类)与子类之间的继承很相似,什么场景下应该采用哪种类型呢?

父类的方法通常也包含了一些功能,子类可以重写父类的方法实现新的功能,接口均为抽象方法,是没有实现的空方法,子类实现该接口时要为这些方法定义对应的功能。如果我们有多态的需求,比如说在调用函数时,形式参数传入接口对象,此时可以依据需求传入不同的子类引用,进而执行不同的功能,这种场景是推荐使用接口与子类这种继承(实现)的,其他情况可以采用父类与子类继承这种模式。

  1. 如果子类除了实现了抽象类的所有方法,又增加了其他的方法,此时算不算实现了接口呢?

算。

package main

import "fmt"

// 本质是一个指针
type AnimalIF interface {
 Sleep()
 GetColor() string // 获取动物的颜色
 GetType() string  // 获取动物的种类
}

// 具体的类
type Cat struct {
 color string // 猫的颜色
}

func (this *Cat) Sleep() {
 fmt.Println("Cat is Sleep...")
}

func (this *Cat) GetColor() string {
 return this.color
}

func (this *Cat) GetType() string {
 return "Cat"
}

type Dog struct {
 color string
}

func (this *Dog) Sleep() {
 fmt.Println("Dog is Sleep...")
}

func (this *Dog) GetColor() string {
 return this.color
}

func (this *Dog) GetType() string {
 return "Dog"
}

func (this *Dog) PrintMsg() string {
 return "Hmm..."
}

func showAnimal(animal AnimalIF) {
 animal.Sleep() // 多态
 fmt.Println("color = ", animal.GetColor())
 fmt.Println("kind = ", animal.GetType())
}

func main() {
 var animal AnimalIF // 接口的数据类型,父类指针
 animal = &Cat{"Green"}
 animal.Sleep() // 调用的就是 Cat 的 Sleep() 方法

 animal = &Dog{"Yellow"}
 animal.Sleep() // 调用 Dog 的 Sleep() 方法,多态现象

 cat := Cat{"Green"}
 dog := Dog{"Yellow"}
 fmt.Println("Dog Print Message: ", dog.PrintMsg())

 showAnimal(&cat)
 showAnimal(&dog)
}

image

0x05 References

  1. Type assertions - https://go.dev/tour/methods/15
  2. https://www.bilibili.com/video/BV1gf4y1r79E?p=20

文章来源: https://mp.weixin.qq.com/s?__biz=Mzg5NjAxNjc5OQ==&mid=2247483880&idx=1&sn=0bc2291ada79e8d3ff1da77168e0651f&chksm=c006c918f771400e9533c504c3e5423ae4a642747649bfb6fcadbcfa3f7b17bf12dbf01b1ade&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh