Go 接口和多态
在讲解具体的接口之前,先看如下问题。
使用面向对象的方式,设计一个加减的计算器
代码如下:
package mainimport "fmt"//父类,这是结构体
type Operate struct {num1 intnum2 int
}//加法子类,这是结构体type Add struct {Operate
}//减法子类,这是结构体type Sub struct {Operate
}//加法子类的方法
func (a *Add) Result() int {return a.num1 + a.num2
}
可以看到ADD里面是用父类结构体的,然后直接返回num1+num2就行了
//减法子类的方法
func (s *Sub) Result() int {return s.num1 - s.num2
}
可以看到Sub里面是用父类结构体的,然后直接返回num1-num2就行了
//方法调用
func main0201() {//创建加法对象//var a Add//a.num1 = 10//a.num2 = 20//v := a.Result()//fmt.Println(v)
//可以看到调用起来还是很简单的,直接给父类结构体的属性赋值,然后调用加法的方法就行。//创建减法对象var s Subs.num1 = 10s.num2 = 20v := s.Result()fmt.Println(v)
}
//可以看到调用起来还是很简单的,直接给父类结构体的属性赋值,然后调用减法的方法就行
以上实现非常简单,但是有个问题,在main()函数中,当我们想使用减法操作时,创建减法类的对象,调用其对应的减法的方法。但是,有一天,系统需求发生了变化,要求使用加法,不再使用减法,那么需要对main()函数中的代码,做大量的修改。将原有的代码注释掉,创建加法的类对象,调用其对应的加法的方法。有没有一种方法,让main()函数,只修改很少的代码就可以解决该问题呢?有,要用到接下来给大家讲解的接口的知识点。
一、 什么是接口
接口就是一种规范与标准,在生活中经常见接口,例如:笔记本电脑的USB接口,可以将任何厂商生产的鼠标与键盘,与电脑进行链接。为什么呢?原因就是,USB接口将规范和标准制定好后,各个生产厂商可以按照该标准生产鼠标和键盘就可以了。
在程序开发中,接口只是规定了要做哪些事情,干什么。具体怎么做,接口是不管的。这和生活中接口的案例也很相似,例如:USB接口,只是规定了标准,但是不关心具体鼠标与键盘是怎样按照标准生产的.
在企业开发中,如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口告诉开发人员你需要实现那些功能。
二、 接口定义
接口定义的语法如下:
//先定义接口 一般以er结尾 根据接口实现功能
type Humaner interface {//方法 方法的声明sayhi()
}
怎样具体实现接口中定义的方法呢?
//Student的结构体
type student11 struct {name stringage intscore int
}
//Student的打印方法
func (s *student11)sayhi() {fmt.Printf("大家好,我是%s,今年%d岁,我的成绩%d分\n",s.name,s.age,s.score)
}
//teacher11的结构体
type teacher11 struct {name stringage intsubject string
}
//teacher11的方法
func (t *teacher11)sayhi() {fmt.Printf("大家好,我是%s,今年%d岁,我的学科是%s\n",t.name,t.age,t.subject)
}
具体的调用如下:
func main() {//接口是一种数据类型 可以接收满足对象的信息//接口是虚的 方法是实的//接口定义规则 方法实现规则//接口定义的规则 在方法中必须有定义的实现var h Humanerstu := student11{"小明",18,98}//stu.sayhi()//将对象信息赋值给接口类型变量h = &stuh.sayhi()
//直接将Student的对象赋值给了h接口,然后就能实现方法的调用tea := teacher11{"老王",28,"物理"}//tea.sayhi()//将对象赋值给接口 必须满足接口中的方法的声明格式h = &teah.sayhi()
}
只要类(结构体)实现对应的接口,那么根据该类创建的对象,可以赋值给对应的接口类型。
接口的命名习惯以er结尾。
三、 多态
接口有什么好处呢?实现多态。
多态就是同一个接口,使用不同的实例而执行不同操作
所谓多态指的是多种表现形式,如下图所示:
使用接口实现多态的方式如下:
package mainimport "fmt"//先定义接口 一般以er结尾 根据接口实现功能
type Humaner1 interface {//方法 方法的声明sayhi()}//student12的结构体
type student12 struct {name stringage intscore int
}
//student12的方法
func (s *student12)sayhi() {fmt.Printf("大家好,我是%s,今年%d岁,我的成绩%d分\n",s.name,s.age,s.score)
}
//teacher12的结构体
type teacher12 struct {name stringage intsubject string
}
//teacher12的方法
func (t *teacher12)sayhi() {fmt.Printf("大家好,我是%s,今年%d岁,我的学科是%s\n",t.name,t.age,t.subject)
}//多态的实现
//将接口作为函数参数 实现多态
func sayhello(h Humaner1) {h.sayhi()
}func main() {stu := student12{"小明",18,98}//调用多态函数sayhello(&stu)tea := teacher12{"老王",28,"Go"}sayhello(&tea)
}
关于接口的定义,以及使用接口实现多态,但是多态有什么好处呢?现在还是以开始提出的计算器案例给大家讲解一下。
四、多态案例
使用多态的功能,实现一个加减计算器。完整代码如下:
package mainimport "fmt"// 定义接口
type Opter interface {// 方法声明Result() int
}// 父类
type Operate struct {num1 intnum2 int
}// 加法子类
type Add struct {Operate
}// 加法子类的方法
func (a *Add) Result() int {return a.num1 + a.num2
}// 减法子类
type Sub struct {Operate
}// 减法子类的方法
func (s *Sub) Result() int {return s.num1 - s.num2
}// 多态实现
func Result(o Opter) {v := o.Result()fmt.Println(v)
}// 上面是定义的方法
func main() {//创建加法对象//var a Add//a.num1 = 10//a.num2 = 20//v := a.Result()//fmt.Println(v)//2.通过接口实现//var o Opter//var a Add = Add{Operate{10, 20}}//o = &a//value := o.Result()//fmt.Println(value)//3.多态实现var a Add = Add{Operate{10, 20}}Result(&a)var s Sub = Sub{Operate{10, 20}}Result(&s)
}30
-10
四、 接口继承与转换
接口也可以实现继承:
// 先定义接口 一般以er结尾 根据接口实现功能
type Humaner2 interface { //子集//方法 方法的声明sayhi()
}type Personer interface { //超集Humaner2 //继承sayhi()sing(string)
}type student13 struct {name stringage intscore int
}func (s *student13) sayhi() {fmt.Printf("大家好,我是%s,今年%d岁,我的成绩%d分\n", s.name, s.age, s.score)
}func (s *student13) sing(name string) {fmt.Println("我为大家唱首歌", name)
}func main() {//接口类型变量定义var h Humaner2var stu student13 = student13{"小吴", 18, 59}h = &stuh.sayhi()//接口类型变量定义var p Personerp = &stup.sayhi()p.sing("大碗面")
}大家好,我是小吴,今年18岁,我的成绩59分
大家好,我是小吴,今年18岁,我的成绩59分
接口继承后,可以实现“超集”接口转换“子集”接口,代码如下:
package mainimport "fmt"// 先定义接口 一般以er结尾 根据接口实现功能
type Humaner2 interface { //子集//方法 方法的声明sayhi()
}type Personer interface { //超集Humaner2 //继承sayhi()sing(string)
}type student13 struct {name stringage intscore int
}func (s *student13) sayhi() {fmt.Printf("大家好,我是%s,今年%d岁,我的成绩%d分\n", s.name, s.age, s.score)
}func (s *student13) sing(name string) {fmt.Println("我为大家唱首歌", name)
}func main() {//接口类型变量定义var h Humaner2 //子集var p Personer //超集var stu student13 = student13{"小吴", 18, 59}p = &stu//将一个接口赋值给另一个接口//超集中包含所有子集的方法h = p //okh.sayhi()//子集不包含超集//不能将子集赋值给超集//p = h //err//p.sayhi()//p.sing("大碗面")
}
五、 空接口
空接口(interface{})不包含任何的方法,正因为如此,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值。例如:
func test1() {fmt.Println("test")
}func main() {// 空接口类型的切片var i []interface{}fmt.Printf("%T\n", i)i = append(i, 1, 3.14, "aaa", test1)fmt.Println(i)for idx := 0; idx < len(i); idx++ {fmt.Println(i[idx])}
}[]interface {}
[1 3.14 aaa 0xd5420]
1
3.14
aaa
0xd5420
相关文章:

Go 接口和多态
在讲解具体的接口之前,先看如下问题。 使用面向对象的方式,设计一个加减的计算器 代码如下: package mainimport "fmt"//父类,这是结构体 type Operate struct {num1 intnum2 int }//加法子类,这是结构体…...

Git忽略文件的几种方法,以及.gitignore文件的忽略规则
目录 .gitignore文件Git忽略规则以及优先级.gitignore文件忽略规则常用匹配示例: 有三种方法可以实现忽略Git中不想提交的文件。1、在Git项目中定义 .gitignore 文件(优先级最高,推荐!)2、在Git项目的设置中指定排除文…...

C语言——指针进阶(2)
继续上次的指针,想起来还有指针的内容还没有更新完,今天来补上之前的内容,上次我们讲了函数指针,并且使用它来实现一些功能,今天我们就讲一讲函数指针数组等内容,废话不多说,我们开始今天的学习…...
【汇编中的寄存器分类与不同寄存器的用途】
汇编中的寄存器分类与不同寄存器的用途 寄存器分类 在计算机体系结构中,8086CPU,寄存器可以分为以下几类: 1. 通用寄存器: 通用寄存器是用于存储数据和执行算术运算的寄存器。在 x86 架构中,这些通用寄存器通常包括…...

基于文本提示的图像目标检测与分割实践
近年来,计算机视觉取得了显着的进步,特别是在图像分割和目标检测任务方面。 最近值得注意的突破之一是分段任意模型(SAM),这是一种多功能深度学习模型,旨在有效地从图像和输入提示中预测对象掩模。 通过利用…...

【4-5章】Spark编程基础(Python版)
课程资源:(林子雨)Spark编程基础(Python版)_哔哩哔哩_bilibili 第4章 RDD编程(21节) Spark生态系统: Spark Core:底层核心(RDD编程是针对这个)Spark SQL:…...

04 卷积神经网络搭建
一、数据集 MNIST数据集是从NIST的两个手写数字数据集:Special Database 3 和Special Database 1中分别取出部分图像,并经过一些图像处理后得到的[参考]。 MNIST数据集共有70000张图像,其中训练集60000张,测试集10000张。所有图…...
【hadoop运维】running beyond physical memory limits:正确配置yarn中的mapreduce内存
文章目录 一. 问题描述二. 问题分析与解决1. container内存监控1.1. 虚拟内存判断1.2. 物理内存判断 2. 正确配置mapReduce内存2.1. 配置map和reduce进程的物理内存:2.2. Map 和Reduce 进程的JVM 堆大小 3. 小结 一. 问题描述 在hadoop3.0.3集群上执行hive3.1.2的任…...
数据结构--6.5二叉排序树(插入,查找和删除)
目录 一、创建 二、插入 三、删除 二叉排序树(Binary Sort Tree)又称为二叉查找树,它或者是一棵空树,或者是具有下列性质的二叉树: ——若它的左子树不为空,则左子树上所有结点的值均小于它的根结构的值…...

无需公网IP,在家SSH远程连接公司内网服务器「cpolar内网穿透」
文章目录 1. Linux CentOS安装cpolar2. 创建TCP隧道3. 随机地址公网远程连接4. 固定TCP地址5. 使用固定公网TCP地址SSH远程 本次教程我们来实现如何在外公网环境下,SSH远程连接家里/公司的Linux CentOS服务器,无需公网IP,也不需要设置路由器。…...
Java工具类
一、org.apache.commons.io.IOUtils closeQuietly() toString() copy() toByteArray() write() toInputStream() readLines() copyLarge() lineIterator() readFully() 二、org.apache.commons.io.FileUtils deleteDirectory() readFileToString() de…...

makefile之使用函数wildcard和patsubst
Makefile之调用函数 调用makefile机制实现的一些函数 $(function arguments) : function是函数名,arguments是该函数的参数 参数和函数名用空格或Tab分隔,如果有多个参数,之间用逗号隔开. wildcard函数:让通配符在makefile文件中使用有效果 $(wildcard pattern) 输入只有一个参…...
算法通关村第十八关——排列问题
LeetCode46.给定一个没有重复数字的序列,返回其所有可能的全排列。例如: 输入:[1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 元素1在[1,2]中已经使…...

基于STM32设计的生理监测装置
一、项目功能要求 设计并制作一个生理监测装置,能够实时监测人体的心电图、呼吸和温度,并在LCD液晶显示屏上显示相关数据。 随着现代生活节奏的加快和环境的变化,人们对身体健康的关注程度越来越高。为了及时掌握自身的生理状况,…...
Go-Python-Java-C-LeetCode高分解法-第五周合集
前言 本题解Go语言部分基于 LeetCode-Go 其他部分基于本人实践学习 个人题解GitHub连接:LeetCode-Go-Python-Java-C Go-Python-Java-C-LeetCode高分解法-第一周合集 Go-Python-Java-C-LeetCode高分解法-第二周合集 Go-Python-Java-C-LeetCode高分解法-第三周合集 G…...
【前端知识】前端加密算法(base64、md5、sha1、escape/unescape、AES/DES)
前端加密算法 一、base64加解密算法 简介:Base64算法使用64个字符(A-Z、a-z、0-9、、/)来表示二进制数据的64种可能性,将每3个字节的数据编码为4个可打印字符。如果字节数不是3的倍数,将会进行填充。 优点࿱…...

leetcode 925. 长按键入
2023.9.7 我的基本思路是两数组字符逐一对比,遇到不同的字符,判断一下typed与上一字符是否相同,不相同返回false,相同则继续对比。 最后要分别判断name和typed分别先遍历完时的情况。直接看代码: class Solution { p…...
[CMake教程] 循环
目录 一、foreach()二、while()三、break() 与 continue() 作为一个编程语言,CMake也少不了循环流程控制,他提供两种循环foreach() 和 while()。 一、foreach() 基本语法: foreach(<loop_var> <items>)<commands> endfo…...

Mojo安装使用初体验
一个声称比python块68000倍的语言 蹭个热度,安装试试 系统配置要求: 不支持Windows系统 配置要求: 系统:Ubuntu 20.04/22.04 LTSCPU:x86-64 CPU (with SSE4.2 or newer)内存:8 GiB memoryPython 3.8 - 3.10g or cla…...

艺术与AI:科技与艺术的完美融合
文章目录 艺术创作的新工具生成艺术艺术与数据 AI与互动艺术虚拟现实(VR)与增强现实(AR)机器学习与互动性 艺术与AI的伦理问题结语 🎉欢迎来到AIGC人工智能专栏~艺术与AI:科技与艺术的完美融合 ☆* o(≧▽≦…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...