【Go】十五、接口、多态、断言

文章目录

1、接口的引入

以日常生活中打招呼为例,定义接口规范,各国人为打招呼为具体的实现

go 复制代码
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(a)
        //中国人打招呼:
        greet(c)
}

2、接口

  • 接口中不能包含任何变量
  • 接口中定义一组方法,但不需要实现
  • Go中没有implements关键字,实现接口要实现所有的方法才是实现,即Go的实现是基于方法的

3、接口的注意点

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

go 复制代码
//直接用接口创建实例并调用方法,编译报错
//var s SayHello
//s.sayHello()
c := Chinese{}
var s SayHello = c
s.sayHello()

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

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

go 复制代码
package main
import "fmt"

type AInterface interface{
        a()
}

type BInterface interface{
        b()
}

type Stu struct{
}

//实现接口A(的方法)
func (s Stu) a(){
        fmt.Println("aaaa")
}
//实现接口B(的方法)
func (s Stu) b(){
        fmt.Println("bbbb")
}

func main(){
        var s Stu
        var a AInterface = s		//注意这里的赋值
    	var b BInterface = s		//注意这里的赋值
        a.a()
        b.b()
}

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

go 复制代码
package main
import "fmt"
//C接口
type CInterface interface{
        c()
}

//B接口
type BInterface interface{
        b()
}

//A接口继承了B、C接口,且有自己的方法a()
type AInterface interface{
        BInterface
        CInterface
        a()
}

//Stu结构体实现A接口,也要去实现B、C接口的方法
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)空接口没有任何方法,所以可以理解为所有类型都实现了空接口,也可以理解为我们可以把任何一个变量赋给空接口

注意上面两种空接口类型的写法,一种是自己定义一个:

go 复制代码
type E interface{
}

Var e E = s

也可:

go 复制代码
var e interface{} = s

4、多态

面向对象的最后一个特征:多态,即多种形态,编译时、运行时两种状态。Go中的多态特征是通过接口实现的,可以按照统一的接口来调用不同的实现。如上面Part1中的SayHello,形参就是一个父类接口:

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

5、断言

直接判断是否是该类型的变量,Java的instanceOf

go 复制代码
value, ok := element.(T)

即,element是否为T类型,是转为T,值为value,且ok为true

go 复制代码
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()
        //断言:
        ch,flag := s.(Chinese)//看s是否能转成Chinese类型并且赋给ch变量,flag是判断是否转成功
        if flag == true{
                ch.niuYangGe()
        }else{
                fmt.Println("美国人不会扭秧歌")
        }
        fmt.Println("打招呼。。。")
}
func main(){
        
        //创建一个中国人:
        //c := Chinese{}
        //创建一个美国人:
        a := American{}
        //美国人打招呼:
        greet(a)
        //中国人打招呼:
        //greet(c)
}

关键点:

6、Type Switch

一种特殊的switch语句,用type关键字。用法:

go 复制代码
//定义一个函数:专门用来各国人打招呼的函数,接收具备SayHello接口的能力的变量:
func greet(s SayHello){
        s.sayHello()
        switch s.(type){//type属于go中的一个关键字,固定写法
                case Chinese:
                        ch := s.(Chinese)
                        ch.niuYangGe()
                case American:
                        am := s.(American)
                        am.disco()
        }
        fmt.Println("打招呼。。。")
}

完整示例:

go 复制代码
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")
}
func (person American) disco(){
        fmt.Println("野狼disco")
}
//定义一个函数:专门用来各国人打招呼的函数,接收具备SayHello接口的能力的变量:
func greet(s SayHello){
        s.sayHello()
        switch s.(type){//type属于go中的一个关键字,固定写法
                case Chinese:
                        ch := s.(Chinese)
                        ch.niuYangGe()
                case American:
                        am := s.(American)
                        am.disco()
        }
        fmt.Println("打招呼。。。")
}
func main(){
        
        //创建一个中国人:
        c := Chinese{}
        //创建一个美国人:
        //a := American{}
        //美国人打招呼:
        //greet(a)
        //中国人打招呼:
        greet(c)
}
相关推荐
程序员-小李15 分钟前
餐厅下单助手系统(Java+MySQL)
java·开发语言·mysql
开心工作室_kaic19 分钟前
springboot496基于java手机销售网站设计和实现(论文+源码)_kaic
java·开发语言·智能手机
像少年啦飞驰点、21 分钟前
SpringBoot + HttpSession 自定义生成sessionId
java·开发语言
raysync88836 分钟前
替代传统FTP传输,镭速大数据传输系统实现安全高效数据流转!
开发语言·安全·php
mask哥37 分钟前
算法:LeetCode470_用Rand7()实现Rand10()_java实现
java·开发语言
搬码后生仔39 分钟前
将 ASP.NET Core 应用程序的日志保存到 D 盘的文件中 (如 Serilog)
后端·asp.net
Suwg20942 分钟前
《手写Mybatis渐进式源码实践》实践笔记(第七章 SQL执行器的创建和使用)
java·数据库·笔记·后端·sql·mybatis·模板方法模式
cr.sheeper1 小时前
CTFHUB-web进阶-php
开发语言·php
Clockwiseee1 小时前
PHP之伪协议
android·开发语言·php
开心工作室_kaic1 小时前
springboot498基于javaweb的宠物猫认养系统(论文+源码)_kaic
java·开发语言·数据库·美食