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 main

import "fmt"

// 定义一个结构体
type Book struct {
	title  string
	author string
}

func main() {

	//可以先定义后初始化
	var book1 Book
	book1.title = "Golang"
	book1.author = "李四"

	//也可以直接在{}中初始化
	book2 := Book{title: "c++", author: "王五"}

	fmt.Println(book1)
	fmt.Println(book2)
}

在这里插入图片描述

2.结构体传参

  • 值传参
    传递的是结构体的拷贝,原结构体不会发生改变
package main

import "fmt"

// 定义一个结构体
type Book struct {
	title  string
	author string
}

func main() {
	var book1 Book
	book1.title = "Golang"
	book1.author = "李四"

	fmt.Println(book1)

	changeBook(book1)
	fmt.Println(book1)
}

func changeBook(book Book) {
	book.author = "张三"
}

在这里插入图片描述

  • 引用传递
    传递的是结构体的指针,原结构体的值会改变
package main

import "fmt"

// 定义一个结构体
type Book struct {
	title  string
	author string
}

func main() {
	var book1 Book
	book1.title = "Golang"
	book1.author = "李四"

	fmt.Println(book1)

	changeBook(&book1)
	fmt.Println(book1)
}

func changeBook(book *Book) {
	book.author = "张三"
}

在这里插入图片描述

二、将结构体变成类

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

type Hero struct {
	Name  string
	Ad    int
	Level int
}

func (this Hero) GetName() string {
	return this.Name
}
  • GetName这个函数前面的(this Hero)表明这个函数是绑定于Hero这个结构体中的成员函数,可以通过this这个参数调用结构体中的成员
package main

import "fmt"

type Hero struct {
	Name  string
	Ad    int
	Level 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 main

import "fmt"

type Hero struct {
	Name  string
	Ad    int
	Level 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 main

import "fmt"

type Human struct {
	name string
	sex  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_go

import "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_go

import "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_go

import "fmt"

// arg这个参数可以接受任意的类型
func allType(arg interface{}) {
	fmt.Println(arg)
}

type Book struct {
	name   string
	author 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_go

import "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   string
	author 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_go

import "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   string
	author string
}

func Interface() {
	book1 := Book{"shijie", "zhangsan"}
	allType(book1)
	allType(120)
	allType(12.5848)
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RXJS中Subject, BehaviorSubject, ReplaySubject, AsyncSubject的区别?

在RxJS(Reactive Extensions for JavaScript)中,Subject、BehaviorSubject、ReplaySubject和AsyncSubject都是Observable的变体,它们用于处理观察者模式中的不同场景。以下是它们之间的主要区别: 1、Subject: 是一种特…

AGI是否应该具备基础的常识模型

通用人工智能(AGI)是指能够理解或学习任何人类或其他动物能够做的智力任务的人工智能系统,它是人工智能领域的终极目标之一。 AGI 的研究范式是指在 AGI 领域中,研究者们所遵循的一些基本的理念、方法和目标。 AGI 是否应该存在基…

使用 Picocli 开发 Java 命令行,5 分钟上手

大家好,我是鱼皮,对不会前端的同学来说,开发 命令行工具 是一种不错的展示系统功能的方式。在 Java 中开发命令行工具也很简单,使用框架,几分钟就能学会啦~ Picocli 入门 Picocli 是 Java 中个人认为功能最完善、最简单…

Android系统开发之浅谈广播接收器回调

广播接器BroadcastReceiver 广播Intent和广播接收器BroadcastReceiver,是大家android开发用的特别多的二个控件。 那如何从系统角度看待广播和广播接收器呢? 对于静态注册BroadcastReceiver和动态注册的BroadcastReceiver是如何回调其onReceive方法呢…

Docker网络配置

网络相关 子网掩码 互联网是由许多小型网络构成的,每个网络上都有许多主机,这样便构成了一个有层次的结构。 IP 地址在设计时就考虑到地址分配的层次特点,将每个 IP地址都分割成网络号和主机号两部分,以便于IP 地址的寻址操作。…

从0到1:实验室设备借用小程序开发笔记

概论 实验室设备借用小程序,适合各大高校,科技园区,大型企业集团的实验室设备借用流程, 通过数字化的手段进一步提升相关单位设备保障水平,规范实验室和设备管理,用户通过手机小程序扫描设备的二维码,可以…

YOLOv5改进系列(26)——添加RFAConv注意力卷积(感受野注意力卷积运算)

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制 YOLOv5改进系列(2)——添加CBAM注意力机制 YOLOv5改进系列&…

Redis在Windows10中安装和配置

1.首先去下载Redis 这里不给出下载地址,自己可以用去搜索一下地址 下载 下载完成后解压到D盘redis下,本人用的是3.2.100 D:\Redis\Redis-x64-3.2.100 2.解压完成后需要设置环境变量,这里新建一个系统环境变量中path 中添加一个文件所…

如何用GPT 运行python?GPT4科研应用与AI绘图及论文高效写作

详情点击链接:如何用GPT 运行python?GPT4科研应用与AI绘图及论文高效写作 一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析,AI画图,图像识别,文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型…

计算机导论07-算法和数据结构

文章目录 算法基础算法及其特性算法的概念算法与程序算法表示 算法的描述自然语言流程图盒图(N-S图)伪代码程序设计语言 算法评价算法的衡量标准算法的规模时间复杂度空间复杂度 数据结构数据结构的概念数据的逻辑结构数据的存储结构数据的基本操作 常用…

6.3.4录制屏幕

6.3.4录制屏幕 除了可以进行声音录制外,Camtasia4还允许录制屏幕上的各种操作,并且在录制视频的同时还可以混入讲解,这在制作视频教程时很有用处。 1.在Camtasia Studio主程序中,单击【工具】|【Camtasia录像器】&am…

抖店商家对接带货主播建议,远离头部主播保平安,附沟通话术模板

我是王路飞。 抖店出单玩法中,商品卡属于靠天吃饭,有一定的风险,所以不建议新手选择。 我们自己包括学生做店,一直都是以达人模式为主的,主要是可控(风险可控,数据可控,流程可控&a…

Qt第二周周二作业

代码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();void paintEvent(…

CAD 相关技巧

空格键&#xff1a; &#xff08;1&#xff09;确认操作 &#xff08;2&#xff09;重复上一步操作删除键&#xff1a;E直线命令&#xff1a;输入L选择方式&#xff1a;框选与点选&#xff0c;对于框选&#xff1a;左框选&#xff0c;必须全部框选完才会被选择&#xff0c;右框…

FTP文件传输协议 、多种方式安装yum仓库

一、网络文件共享服务 1.存储类型分三种&#xff1a; 直连式存储&#xff1a;Direct-Attached Storage&#xff0c;简称DAS 存储区域网络&#xff1a;Storage Area Network&#xff0c;简称SAN&#xff08;可以使用空间&#xff0c;管理也是你来管理&#xff09; 网络附加存储…

【算法分析与设计】跳跃游戏

题目 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j < n 返回到达 nums[n - …

液晶偏振光栅

1、偏振 光是横波.在垂直于光的传播方向的平面内光波振动(即E矢量振动) 各方向振幅都相等的光为自然光; 只在某一方向有光振动的光称为线偏振光;各方向光振动都有,但振幅不同的光叫部分偏振光.螺旋着振动的光称圆偏振光&#xff0c;分旋和右旋 2、庞加莱球表示法 庞加莱球是用…

框架基础-Maven+SpringBoot入门

框架基础 Maven基础 Maven概述 Maven是为Java项目提供项目构建和依赖管理的工具 Maven三大功能 - 项目构建构建&#xff1a;是一个将代码从开发阶段到生产阶段的一个过程&#xff1a;清理&#xff0c;编译&#xff0c;测试&#xff0c;打包&#xff0c;安装&#xff0c;部署…

解决kali beef启动失败解问题

只限于出现这个提示的时候使用 卸载 ruby apt remove ruby 卸载 beef apt remove beef-xss 重新安装ruby apt-get install ruby apt-get install ruby-dev libpcap-dev gem install eventmachine 重新安装beef apt-get install beef-xss 弄完以上步骤如果还是不行就重启kali再试…

Axure租房平台用户端APP原型图,房屋租赁高保真模板45页

作品概况 页面数量&#xff1a;共 40 页 兼容软件&#xff1a;仅支持Axure RP 9/10&#xff0c;非程序软件无源代码 应用领域&#xff1a;租房平台、房屋租赁领域 作品特色 本作品为房屋租赁用户端app原型&#xff0c;产品定位为&#xff1a;提供本地租房信息、出租房源信息…
最新文章