Go后端开发 -- 面向对象特征:结构体 继承 多态 interface

Go后端开发 – 面向对象特征:结构体 && 继承 && 多态 && interface

文章目录

  • Go后端开发 -- 面向对象特征:结构体 && 继承 && 多态 && interface
  • 一、Go的结构体
    • 1.结构体的声明和定义
    • 2.结构体传参
  • 二、将结构体变成类
    • 1.向结构体中添加成员函数
    • 2.结构体定义的访问权限问题
  • 三、Golang面向对象的继承
  • 四、interface接口与多态
    • 1.由interface实现多态
    • 2.通用万能类型
    • 3.类型断言


一、Go的结构体

1.结构体的声明和定义

  • type用来声明数据类型
//声明一种新的数据类型myint,是int的一个别名
type myint int
  • 使用type定义结构体
  • 对于结构体对象:
    可以先定义后初始化;
    也可以直接在{}中初始化
package mainimport "fmt"// 定义一个结构体
type Book struct {title  stringauthor string
}func main() {//可以先定义后初始化var book1 Bookbook1.title = "Golang"book1.author = "李四"//也可以直接在{}中初始化book2 := Book{title: "c++", author: "王五"}fmt.Println(book1)fmt.Println(book2)
}

在这里插入图片描述

2.结构体传参

  • 值传参
    传递的是结构体的拷贝,原结构体不会发生改变
package mainimport "fmt"// 定义一个结构体
type Book struct {title  stringauthor string
}func main() {var book1 Bookbook1.title = "Golang"book1.author = "李四"fmt.Println(book1)changeBook(book1)fmt.Println(book1)
}func changeBook(book Book) {book.author = "张三"
}

在这里插入图片描述

  • 引用传递
    传递的是结构体的指针,原结构体的值会改变
package mainimport "fmt"// 定义一个结构体
type Book struct {title  stringauthor string
}func main() {var book1 Bookbook1.title = "Golang"book1.author = "李四"fmt.Println(book1)changeBook(&book1)fmt.Println(book1)
}func changeBook(book *Book) {book.author = "张三"
}

在这里插入图片描述

二、将结构体变成类

1.向结构体中添加成员函数

type Hero struct {Name  stringAd    intLevel int
}func (this Hero) GetName() string {return this.Name
}
  • GetName这个函数前面的(this Hero)表明这个函数是绑定于Hero这个结构体中的成员函数,可以通过this这个参数调用结构体中的成员
package mainimport "fmt"type Hero struct {Name  stringAd    intLevel int
}func (hero Hero) GetName() string {return hero.Name
}func (hero Hero) SetName(newName string) {hero.Name = newName
}func main() {hero1 := Hero{Name: "zhangsan", Ad: 25, Level: 3}fmt.Println(hero1)name1 := hero1.GetName()fmt.Println(name1)hero1.SetName("超人")fmt.Println(hero1)
}

在这里插入图片描述
可以看到getName可以获取结构体对象中的成员变量,但是setName函数没有改变对象中的值

  • 因为hero这个参数是调用该方法的对象的一个拷贝
    在这里插入图片描述
  • 将所有的hero参数都改为*Hero类型,那么hero参数就是调用该方法的对象的指针了,指向该对象的地址空间,能够改变对象的成员变量的值
  • 因此对所有的成员函数,该参数都应该定义为指针类型的参数
package mainimport "fmt"type Hero struct {Name  stringAd    intLevel int
}func (hero *Hero) GetName() string {return hero.Name
}func (hero *Hero) SetName(newName string) {hero.Name = newName
}func main() {hero1 := Hero{Name: "zhangsan", Ad: 25, Level: 3}fmt.Println(hero1)name1 := hero1.GetName()fmt.Println(name1)hero1.SetName("超人")fmt.Println(hero1)
}

在这里插入图片描述

2.结构体定义的访问权限问题

上面实例的结构体类型Hero的首字母是大写的
go语言的封装是针对包来封装的,类的公有和私有都是针对包来的

  • 类名首字母大写,代表其他包可以访问该类,可以定义该类对象
    在这里插入图片描述

  • 类的属性首字母大写,表示该属性是对外能够访问的(public),否则只能类的内部访问(private)
    在这里插入图片描述

三、Golang面向对象的继承

go中的面向对象的继承没有公有、私有继承,只有一种类型的继承

实例:

package mainimport "fmt"type Human struct {name stringsex  string
}func (human *Human) Eat() {fmt.Println("Human.Eat()...")
}func (human *Human) Walk() {fmt.Println("Human.Walk()...")
}type Superman struct {Human //表示Superman类继承了Human类的方法level int
}// 重定义父类方法
func (superman *Superman) Eat() {fmt.Println("Superman.Eat()...")
}// 定义子类的新方法
func (superman *Superman) Fly() {fmt.Println("Superman.Fly()...")
}func main() {h1 := Human{name: "zhangsan", sex: "male"}h1.Eat()h1.Walk()//定义一个子类对象s1 := Superman{Human{"蝙蝠侠", "male"}, 3}s1.Eat()  //子类重写的成员函数s1.Walk() //父类成员函数s1.Fly()  //子类独有成员函数
}

在这里插入图片描述

  • 上述实例中,Superman继承了Human类,也就是继承了父类的全部成员
  • 子类可以对父类的成员函数进行重写,也可以调用父类的成员函数
  • 子类可以直接访问父类的成员变量
    在这里插入图片描述

四、interface接口与多态

1.由interface实现多态

Golang中的多态需要依赖interface接口实现;

  • interface类型,本质是一个父类指针,用于定义接口,底层是指针指向函数列表
type AnimalIF interface {Sleep()GetColor() string //获取动物颜色GetType() string  //获取动物类别
}
  • 如果一个类实现了interface中的所有方法,就代表该类实现了当前的interface接口,就可以实现多态,interface类型的的指针就可以指向该类的对象了
  • 若一个类没有完全重写interface中的所有方法,则interface指针无法指向该类

实例

package interface_goimport "fmt"// 本质是一个父类指针,用于定义接口,底层是指针指向函数列表
type AnimalIF interface {Sleep()GetColor() string //获取动物颜色GetType() string  //获取动物类别
}// 具体的类
type Cat struct {//无需在子类中继承interface,只需要实现interface的方法,就可以实现多态//这样就可以用interface的指针去指向Cat对象color string //猫的颜色
}// 重写interface接口中的方法
// Cat类重写了interface中的所有方法,就代表该类实现了当前的接口
// 若Cat类没有完全重写interface中的所有方法,则interface指针无法指向该类
func (c *Cat) Sleep() {fmt.Println("Cat is sleep")
}func (c *Cat) GetColor() string {return c.color
}func (c *Cat) GetType() string {return "Cat"
}type Dog struct {color string
}func (d *Dog) Sleep() {fmt.Println("Dog is sleep")
}func (d *Dog) GetColor() string {return d.color
}func (d *Dog) GetType() string {return "Dog"
}// 使用父类指针来接受子类对象
func showAnimal(animal AnimalIF) {animal.Sleep()fmt.Println("color = ", animal.GetColor())fmt.Println("type = ", animal.GetType())
}func Interface() {var animal AnimalIF     //接口的数据类型,也就是父类的指针animal = &Cat{"yellow"} //通过匿名对象的指针给接口赋值,animal.Sleep()          //调用的就是Cat的Sleep()方法animal = &Dog{"black"}fmt.Println(animal.GetColor()) //调用的就是Dog的GetColor()方法,多态的现象
}

在这里插入图片描述

  • 上述实例中,创建了名为AnimalIF的interface接口,包含三个方法

  • Cat和Dog类重写了AnimalIF的所有接口,因此AnimalIF指针可以指向Cat和Dog类的对象,进而实现多态

  • 还可以通过AnimalIF类型的指针,接受Cat和Dog类对象的地址,这样也可以体现出多态

package interface_goimport "fmt"// 本质是一个父类指针,用于定义接口,底层是指针指向函数列表
type AnimalIF interface {Sleep()GetColor() string //获取动物颜色GetType() string  //获取动物类别
}// 具体的类
type Cat struct {//无需在子类中继承interface,只需要实现interface的方法,就可以实现多态//这样就可以用interface的指针去指向Cat对象color string //猫的颜色
}// 重写interface接口中的方法
// Cat类重写了interface中的所有方法,就代表该类实现了当前的接口
// 若Cat类没有完全重写interface中的所有方法,则interface指针无法指向该类
func (c *Cat) Sleep() {fmt.Println("Cat is sleep")
}func (c *Cat) GetColor() string {return c.color
}func (c *Cat) GetType() string {return "Cat"
}type Dog struct {color string
}func (d *Dog) Sleep() {fmt.Println("Dog is sleep")
}func (d *Dog) GetColor() string {return d.color
}func (d *Dog) GetType() string {return "Dog"
}// 使用父类指针来接受子类对象
func showAnimal(animal AnimalIF) {animal.Sleep()fmt.Println("color = ", animal.GetColor())fmt.Println("type = ", animal.GetType())
}func Interface() {c1 := Cat{"yellow"}d1 := Dog{"white"}showAnimal(&c1)showAnimal(&d1)
}

在这里插入图片描述

2.通用万能类型

interface{}空接口:为Golang的万能类型,基本类型如int, string, float32, float64, struct等都实现了interface{}(因为空接口中没有具体的接口),因此interface{}这种类型的变量可以引用任意的数据类型

实例:

package interface_goimport "fmt"// arg这个参数可以接受任意的类型
func allType(arg interface{}) {fmt.Println(arg)
}type Book struct {name   stringauthor string
}func Interface() {book1 := Book{"shijie", "zhangsan"}allType(book1)allType(120)allType(12.5848)
}

在这里插入图片描述

  • 在上述实例中,函数allType的参数arg的类型是interface{},是通用万能类型,能够接受任意类型的参数

3.类型断言

Golang为interface{}类型提供了类型断言,用于判断interface{}类型变量引用的参数底层数据类型是什么

  • 断言的格式为:
    value, ok := arg.(string)
    如果断言成功,即arg是string类型,则value被赋值为string类型的arg的值,ok被赋值为true;否则value为空,ok为false

实例:

package interface_goimport "fmt"// arg这个参数可以接受任意的类型
func allType(arg interface{}) {fmt.Println(arg)//interface{}改如何区分 此时引用的底层数据类型到底是什么value, ok := arg.(string)if ok {fmt.Println("arg is string type, value = ", value)} else {fmt.Println("arg is not string type")}
}type Book struct {name   stringauthor string
}func Interface() {book1 := Book{"shijie", "zhangsan"}allType(book1)allType(120)allType(12.5848)
}

在这里插入图片描述

  • interface{}断言可以配合switch语句使用,switch t := arg.(type) { }是switch语句的独有断言方式,arg.(type)不可脱离switch语句单独使用
package interface_goimport "fmt"// arg这个参数可以接受任意的类型
func allType(arg interface{}) {switch t := arg.(type) {case string:fmt.Println("arg is string type, value = ", t)case int:fmt.Println("arg is int type, value = ", t)case float32:fmt.Println("arg is float32 type, value = ", t)case float64:fmt.Println("arg is float64 type, value = ", t)default:fmt.Println("arg is unexpected type")}
}type Book struct {name   stringauthor string
}func Interface() {book1 := Book{"shijie", "zhangsan"}allType(book1)allType(120)allType(12.5848)
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/409660.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Docker】Dockerfile构建最小镜像

🥳🥳Welcome 的Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于Docker的相关操作吧 目录 🥳🥳Welcome 的Huihuis Code World ! !🥳🥳 前言 一.Dockerfile是什么 二.Dock…

C盘满了,我用什么思路清理?

20240115 上周六同事传了一个很大的虚拟机给我,C盘就红了 虽然是飞秋选错了存储文件的路径,但后来忘了,就开始毫无目的删除文件,过程中会有没有权限删除的,这样还是没有改善。 咨询了公司IT技术人员, 告…

【开源】基于JAVA语言的网上药店系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 药品类型模块2.3 药品档案模块2.4 药品订单模块2.5 药品收藏模块2.6 药品资讯模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 角色表3.2.2 药品表3.2.3 药品订单表3.2.4 药品收藏表3.2.5 药品留言表…

布隆过滤器四种实现(Java,Guava,hutool,Redisson)

1.背景 为预防大量黑客故意发起非法的时间查询请求,造成缓存击穿,建议采用布隆过滤器的方法解决。布隆过滤器通过一个很长的二进制向量和一系列随机映射函数(哈希函数)来记录与识别某个数据是否在一个集合中。如果数据不在集合中…

DataXCloud部署与配置[智数通]

静态IP设置 # 修改网卡配置文件 vim /etc/sysconfig/network-scripts/ifcfg-ens33# 修改文件内容 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic IPADDR192.168.18.130 NETMASK255.255.255.0 GATEWAY192.168.18.2 DEFROUTEyes IPV4_FAILURE_FATALno IPV6INIT…

瑞_Java开发手册_(七)设计规约

文章目录 设计规约的意义设计规约 🙊前言:本文章为瑞_系列专栏之《Java开发手册》的设计规约篇。由于博主是从阿里的《Java开发手册》学习到Java的编程规约,所以本系列专栏主要以这本书进行讲解和拓展,有需要的小伙伴可以点击链接…

SpringBoot项目的两种发布方式(jar包和war包)

SpringBoot项目的两种发布方式&#xff08;jar包和war包&#xff09; 在springboot入门和项目示例这个项目和application.yml配置端口号和访问url路径基础上进行修改 1、使用jar包方式发布 1.1、在pom.xml中添加一个SpringBoot的构建的插件 <build><plugins>&l…

【MYSQL】事务隔离级别

脏读、幻读、不可重复读 脏读 一个事务正在对一条记录做修改&#xff0c;在这个事务完成并提交前&#xff0c;另一个事务也来读取同一条记录&#xff0c;读取了这些未提交的“脏”数据&#xff0c;并据此做进一步的处理&#xff0c;就会产生未提交的数据依赖关系。这种现象被形…

走迷宫(c语言)

前言&#xff1a; 制作一个迷宫游戏是一个有趣的编程挑战。首先&#xff0c;我们需要设计一个二维数组来表示迷宫的布局&#xff0c;其中每个元素代表迷宫中的一个格子。我们可以使用不同的值来表示空格、墙壁和起点/终点。接下来&#xff0c;我们需生成迷宫。在生成迷宫的过程…

Qt 国产嵌入式操作系统实现文字转语音功能(TTS)

1.简介 本示例使用的CPU&#xff1a;rk3588。 操作系统&#xff1a;kylin V10 架构&#xff1a;aarch64 在Windows端&#xff0c;我们很容易想到使用Qt自带的类QTextToSpeech来实现文字转语音功能&#xff0c;Qt版本得在5.11.0以上才支持。但是在嵌入式平台&#xff0c;尤其…

数据仓库(2)-认识数仓

1、数据仓库是什么 数据仓库 &#xff0c;由数据仓库之父比尔恩门&#xff08;Bill Inmon&#xff09;于1990年提出&#xff0c;主要功能仍是将组织透过资讯系统之联机事务处理(OLTP)经年累月所累积的大量资料&#xff0c;透过数据仓库理论所特有的资料储存架构&#xff0c;做…

springboot第49集:【思维导图】多线程,常用类与基础API,集合框架,泛型,数据结构源码...

多线程创建方式一&#xff1a;继承Thread类多线程创建方式二&#xff1a;实现Runnable接口jdk5.0新增两种创建多线程的方式 image.png image.png image.png image.png image.png new Thread(new Runnable() {public void run() {for (int i 1; i < 100; i) {if (i % 2 0) …