第9章 面向对象—接口多态断言

2023年 8月 2日 81.4k 0

接口的引入

【1】代码入门:

package main

import "fmt"

//接口的定义:定义规则、定义规范,定义某种能力:
type SayHello interface{
	sayHello()
}

//接口的实现:定义一个结构体:
//中国人:
type Chinese struct{
	
}

//实现接口的方法---》具体的实现:
func (person Chinese) sayHello(){
	fmt.Println("你好")
}

//接口的实现:定义一个结构体:
//美国人:
type American struct{
	
}

//实现接口的方法---》具体的实现:
func (person American) sayHello()  {
	fmt.Println("hi")
}

//定义一个函数:专门用来各国人打招呼的函数,接收具备SayHello接口的能力的变量:
func greet(s SayHello)  {
	s.sayHello()
}


func main(){

	c := Chinese{}
	a := American{}
	greet(c)
	greet(a)
	
}

【2】总结:

(1)接口中可以定义一组方法,但不需要实现,不需要方法体。并且接口中不能包含任何变量。到某个自定义类型要使用的时候(实现接口的时候),再根据具体情况把这些方法具体实现出来。

(2)实现接口要实现所有的方法才是实现。

(3)Golang中的接口不需要显式的实现接口。Golang中没有implement关键字。

(Golang中实现接口是基于方法的,不是基于接口的)

例如:

A接口 a,b方法

B接口 a,b方法

C结构体 实现了 a,b方法 ,那么C实现了A接口,也可以说实现了B接口 (只要实现全部方法即可,和实际接口耦合性很低,比Java松散得多)

(4)接口目的是为了定义规范,具体由别人来实现即可。

接口注意事项

【1】接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量。

// 直接用接口创建实例,出错:
	// var s SayHello
	// s.sayHello()

【2】只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型。

type integer int

func (i integer) sayHello()  {
	fmt.Println("say hi + ",i)
}

func main(){

	var i integer = 10
	s = i
	s.sayHello()
}

【3】一个自定义类型可以实现多个接口

package main

import "fmt"

type AInterface interface{
	a()
}

type BInterface interface{
	b()
}

type Stu struct{

}

func (s Stu) a() {
	fmt.Println("this is a()")
}

func (s Stu) b() {
	fmt.Println("this is b()")
}

func main()  {
	var s Stu;
	var a AInterface = s
	var b BInterface = s
	a.a()
	b.b()
}

【4】一个接口(比如A接口)可以继承多个别的接口(比如B,C接口),这时如果要实现A接口,也必须将B,C接口的方法也全部实现。

package main

import "fmt"

type CInterface interface{
	c()
}

type BInterface interface{
	b()
}

type AInterface interface{
	CInterface
	BInterface
	a()
}

type Stu struct{

}

func (s Stu) a() {
	fmt.Println("a")
}

func (s Stu) b()  {
	fmt.Println("b")
}

func (s Stu) c() {
	fmt.Println("c")
}



func main()  {
	var s Stu
	var a AInterface = s
	a.a()
	a.b()
	a.c()
}

【5】interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用,那么会输出nil

【6】空接口没有任何方法,所以可以理解为所有类型都实现了空接口,也可以理解为我们可以把任何一个变量赋给空接口。

type E interface {

}

func main()  {
	
	var e E = s
	fmt.Println(e)
	var e2 interface{} = s
	fmt.Println(e2)
	var num float32 = 9.99
	var e3 interface{} = num
	fmt.Println(e3)
}

多态

【1】基本介绍

变量(实例)具有多种形态。面向对象的第三大特征,在Go语言,多态特征是通过接口实现的。可以按照统一的接口来调用不同的实现。这时接口变量就呈现不同的形态。

【2】案例:

//定义一个函数:专门用来各国人打招呼的函数,接收具备SayHello接口的能力的变量:
func greet(s SayHello)  {
	s.sayHello()
}

【3】接口体现多态特征

1) 多态参数: s叫多态参数

2) 多态数组 :

比如:定义SayHello数组,存放中国人结构体、美国人结构体

var arr [3]SayHello
	arr[0] = American{"Rose"}
	arr[1] = Chinese{"菜园子"}
	arr[2] = Chinese{"蜘蛛侠"}

	fmt.Println(arr)

断言

【1】什么是断言?

Go语言里面有一个语法,可以直接判断是否是该类型的变量: value, ok := element.(T),这里value就是变量的值,ok是一个bool类型,element是interface变量,T是断言的类型。

【2】断言的案例引入:

package main

import "fmt"

type SayHello interface{
	sayHello()
}

type Chinese struct{
	name string
}

func (person Chinese) sayHello(){
	fmt.Println("你好")
}

func (person Chinese) niuYangGe(){
	fmt.Println("扭秧歌")
}

type American struct{
	name string
}

func (person American) sayHello(){
	fmt.Println("hi")
}

//定义一个函数:专门用来各国人打招呼的函数,接收具备SayHello接口的能力的变量:
func greet(s SayHello)  {
	s.sayHello()
	//断言:
	//看s是否能转成Chinese类型并且赋给ch变量,flag是判断是否转成功
	var ch Chinese = s.(Chinese)
	ch.niuYangGe()
	fmt.Println("打招呼")
}


func main()  {
	c := Chinese{}
	greet(c)

	// a := American{}
	// greet(a)
}

解决第二个返回值问题:

//定义一个函数:专门用来各国人打招呼的函数,接收具备SayHello接口的能力的变量:
func greet(s SayHello)  {
	s.sayHello()
	//断言:
	//看s是否能转成Chinese类型并且赋给ch变量,flag是判断是否转成功
	// var ch Chinese = s.(Chinese)
	// ch.niuYangGe()

	ch,flag := s.(Chinese)
	if flag == true {
		ch.niuYangGe()
	} else {
		fmt.Println("美国人不会扭秧歌")
	}

	fmt.Println("打招呼")
}

【3】Type Switch 的基本用法

Type Switch 是 Go 语言中一种特殊的 switch 语句,它比较的是类型而不是具体的值。它判断某个接口变量的类型,然后根据具体类型再做相应处理。

func (person American) disco() {
	fmt.Println("野狼disco")
}
//定义一个函数:专门用来各国人打招呼的函数,接收具备SayHello接口的能力的变量:
func greet(s SayHello)  {
	s.sayHello()
	//断言:
	//看s是否能转成Chinese类型并且赋给ch变量,flag是判断是否转成功
	// var ch Chinese = s.(Chinese)
	// ch.niuYangGe()

	// ch,flag := s.(Chinese)
	// if flag == true {
	// 	ch.niuYangGe()
	// } else {
	// 	fmt.Println("美国人不会扭秧歌")
	// }

	switch s.(type) {
		case Chinese:
			ch := s.(Chinese)
			ch.niuYangGe()
		case American:
			am := s.(American)
			am.disco()
	}
	

	fmt.Println("打招呼")
}

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论