Go 接口和多态

这篇具有很好参考价值的文章主要介绍了Go 接口和多态。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在讲解具体的接口之前,先看如下问题。

使用面向对象的方式,设计一个加减的计算器

代码如下:

package main

import "fmt"

//父类,这是结构体
type Operate struct {
    num1 int
    num2 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 Sub
    s.num1 = 10
    s.num2 = 20
    v := s.Result()
    fmt.Println(v)
}
//可以看到调用起来还是很简单的,直接给父类结构体的属性赋值,然后调用减法的方法就行

以上实现非常简单,但是有个问题,在main()函数中,当我们想使用减法操作时,创建减法类的对象,调用其对应的减法的方法。但是,有一天,系统需求发生了变化,要求使用加法,不再使用减法,那么需要对main()函数中的代码,做大量的修改。将原有的代码注释掉,创建加法的类对象,调用其对应的加法的方法。有没有一种方法,让main()函数,只修改很少的代码就可以解决该问题呢?有,要用到接下来给大家讲解的接口的知识点。

一、 什么是接口

接口就是一种规范与标准,在生活中经常见接口,例如:笔记本电脑的USB接口,可以将任何厂商生产的鼠标与键盘,与电脑进行链接。为什么呢?原因就是,USB接口将规范和标准制定好后,各个生产厂商可以按照该标准生产鼠标和键盘就可以了。

在程序开发中,接口只是规定了要做哪些事情,干什么。具体怎么做,接口是不管的。这和生活中接口的案例也很相似,例如:USB接口,只是规定了标准,但是不关心具体鼠标与键盘是怎样按照标准生产的.

在企业开发中,如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口告诉开发人员你需要实现那些功能。

二、 接口定义

接口定义的语法如下:

//先定义接口 一般以er结尾 根据接口实现功能
type Humaner interface {
  //方法 方法的声明
  sayhi()
}

怎样具体实现接口中定义的方法呢?

//Student的结构体
type student11 struct {
    name  string
    age   int
    score int
}
//Student的打印方法
func (s *student11)sayhi()  {
    fmt.Printf("大家好,我是%s,今年%d岁,我的成绩%d分\n",s.name,s.age,s.score)
}
//teacher11的结构体
type teacher11 struct {
    name    string
    age     int
    subject string
}
//teacher11的方法
func (t *teacher11)sayhi()  {
    fmt.Printf("大家好,我是%s,今年%d岁,我的学科是%s\n",t.name,t.age,t.subject)
}

具体的调用如下:

func main() {
    //接口是一种数据类型 可以接收满足对象的信息
    //接口是虚的  方法是实的
    //接口定义规则  方法实现规则
    //接口定义的规则  在方法中必须有定义的实现
    var h Humaner

    stu := student11{"小明",18,98}
    //stu.sayhi()
    //将对象信息赋值给接口类型变量
    h = &stu
    h.sayhi()
//直接将Student的对象赋值给了h接口,然后就能实现方法的调用
    tea := teacher11{"老王",28,"物理"}
    //tea.sayhi()
    //将对象赋值给接口 必须满足接口中的方法的声明格式
    h = &tea
    h.sayhi()
}

只要类(结构体)实现对应的接口,那么根据该类创建的对象,可以赋值给对应的接口类型。

接口的命名习惯以er结尾。

三、 多态

接口有什么好处呢?实现多态。

多态就是同一个接口,使用不同的实例而执行不同操作

所谓多态指的是多种表现形式,如下图所示:
Go 接口和多态,Go,golang,开发语言,后端

使用接口实现多态的方式如下:

package main

import "fmt"

//先定义接口  一般以er结尾  根据接口实现功能
type Humaner1 interface {
    //方法  方法的声明
    sayhi()

}

//student12的结构体
type student12 struct {
    name  string
    age   int
    score int
}
//student12的方法
func (s *student12)sayhi()  {
    fmt.Printf("大家好,我是%s,今年%d岁,我的成绩%d分\n",s.name,s.age,s.score)
}
//teacher12的结构体
type teacher12 struct {
    name    string
    age     int
    subject 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 main

import "fmt"

// 定义接口
type Opter interface {
	// 方法声明
	Result() int
}

// 父类
type Operate struct {
	num1 int
	num2 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  string
	age   int
	score 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 stu student13 = student13{"小吴", 18, 59}
	h = &stu
	h.sayhi()

	//接口类型变量定义
	var p Personer
	p = &stu
	p.sayhi()
	p.sing("大碗面")
}


大家好,我是小吴,今年18岁,我的成绩59分
大家好,我是小吴,今年18岁,我的成绩59

接口继承后,可以实现“超集”接口转换“子集”接口,代码如下:

package main

import "fmt"

// 先定义接口  一般以er结尾  根据接口实现功能
type Humaner2 interface { //子集
	//方法  方法的声明
	sayhi()
}

type Personer interface { //超集
	Humaner2 //继承sayhi()

	sing(string)
}

type student13 struct {
	name  string
	age   int
	score 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 //ok

	h.sayhi()

	//子集不包含超集
	//不能将子集赋值给超集
	//p = h  //err
	//p.sayhi()
	//p.sing("大碗面")
}

五、 空接口

空接口(interface{})不包含任何的方法,正因为如此,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值。例如:文章来源地址https://www.toymoban.com/news/detail-704953.html

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 接口和多态的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • go语言(十二)----多态

    一. 多态的基本要素 有一个父类(有接口) 有子类(实现了父类的全部方法) 父类类型的变量(指针)指向(引用)子类的具体数据变量 首先,定义一个父类 其次,有一个子类 最后,是赋值 完整例子: 当然,也可以这么写:

    2024年01月21日
    浏览(28)
  • Golang:Go语言结构

    在我们开始学习 Go 编程语言的基础构建模块前,让我们先来了解 Go 语言最简单程序的结构。 Go 语言的基础组成有以下几个部分: 包声明 引入包 函数 变量 语句 表达式 注释 接下来让我们来看下简单的代码,该代码输出了\\\"Hello World!\\\": 让我们来看下以上程序的各个部分: 第一

    2024年02月10日
    浏览(50)
  • golang实现webgis后端开发

    目录 前言 二、实现步骤 1.postgis数据库和model的绑定 2.将pg库中的要素转换为geojson (1)几何定义 (2)将wkb解析为几何类型 (3)定义geojson类型 (4)数据转换 (5)数据返回  2.前端传入的geojson储存到数据库 3、其他功能实现 总结         停更了接近一个月都在研究一门新语言gola

    2024年02月08日
    浏览(40)
  • go 结构体 - 值类型、引用类型 - 结构体转json类型 - 指针类型的种类 - 结构体方法 - 继承 - 多态(interface接口) - 练习

    目录 一、结构体 1、python 与 go面向对象的实现: 2、初用GO中的结构体:(实例化一个值类型的数据(结构体)) 输出结果不同的三种方式  3、实例化一个引用类型的数据(结构体) 4、引用类型(指针类型) vs 值类型(两者的区别) 引用类型(指针类型) - 值类型内存拓扑图:

    2024年02月14日
    浏览(37)
  • 【Golang】VScode配置Go语言环境

    安装VScode请参考我的上一篇博客:VScode安装_㫪548的博客-CSDN博客 接下来我们直接进入正题: Go语言(又称Golang)是一种开源的编程语言,由Google开发并于2009年首次发布。Go语言具有简洁、高效、可靠和易于阅读的特点,被设计用于解决大型项目的开发需求。它结合了静态类型

    2024年02月03日
    浏览(55)
  • 【GoLang】MAC安装Go语言环境

    小试牛刀 首先安装VScode软件 或者pycharm mac安装brew软件  brew install go 报了一个错误 不提供这个支持  重新brew install go 之后又重新brew reinstall go 使用go version 可以看到go 的版本 使用go env  可以看到go安装后的配置 配置一个环境变量 vim ~/.zshrc,  

    2024年02月15日
    浏览(45)
  • Go语言(Golang)数据库编程

    要想连接到 SQL 数据库,首先需要加载目标数据库的驱动,驱动里面包含着于该数据库交互的逻辑。 sql.Open() 数据库驱动的名称 数据源名称 得到一个指向 sql.DB 这个 struct 的指针 sql.DB 是用来操作数据库的,它代表了0个或者多个底层连接的池,这些连接由sql 包来维护,sql 包会

    2024年02月03日
    浏览(68)
  • 【Golang】Golang进阶系列教程--Go 语言切片是如何扩容的?

    在 Go 语言中,有一个很常用的数据结构,那就是切片(Slice)。 切片是一个拥有相同类型元素的可变长度的序列,它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。 切片是一种引用类型,它有三个属性:指针,长度和容量。 底层源码定义如下: 指针: 指向

    2024年02月14日
    浏览(43)
  • 【Golang】Golang进阶系列教程--Go 语言 map 如何顺序读取?

    Go 语言中的 map 是一种非常强大的数据结构,它允许我们快速地存储和检索键值对。 然而,当我们遍历 map 时,会有一个有趣的现象,那就是输出的键值对顺序是不确定的。 先看一段代码示例: 当我们多执行几次这段代码时,就会发现,输出的顺序是不同的。 首先,Go 语言

    2024年02月14日
    浏览(47)
  • 【Golang】Golang进阶系列教程--Go 语言数组和切片的区别

    在 Go 语言中,数组和切片看起来很像,但其实它们又有很多的不同之处,这篇文章就来说说它们到底有哪些不同。 数组和切片是两个常用的数据结构。它们都可以用于存储一组相同类型的元素,但在底层实现和使用方式上存在一些重要的区别。 Go 中数组的长度是不可改变的

    2024年02月15日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包