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

news2024/11/20 4:49:05

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.coloradmin.cn/o/1389494.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

嵌入式一开始要怎么学?

今日话题,嵌入式一开始要怎么学?废话不多说,我认为学习嵌入式编程无需观看视频,拥有好的文档比视频更有帮助。掌握一门编程语言是学好嵌入式的关键。现今有许多计算机编程语言可供选择,比如C语言和C等。如果你刚刚入门…

CDN(内容分发网络)和DNS(域名系统)的区别

CDN关注于提高网站的访问速度和性能,主要通过在全球范围内分布的服务器缓存内容来实现,而DNS则是将域名转换为IP地址的系统,是互联网上进行任何形式的数据交换和通信的基础。 CDN(内容分发网络) 目的:CDN的…

查看centos的CPU、内存、磁盘空间等配置信息

目录 查看CPU/proc/cpuinfo中的信息 查看内存/proc/meminfo中的信息 查看磁盘空间df 命令du命令使用fdisk命令 查看CPU /proc/cpuinfo中的信息 前置: [ltkjltkj front]$ cat /proc/cpuinfo| grep "physical id" physical id : 0 physical id : 0 physi…

GO——gin中间件和路由

中间件 参考:https://learnku.com/articles/66234 结构 中间件是函数中间件函数被放在调用链上调用链的末尾是路由path对应的函数 执行过程 net/http包调用到gin的serverHTTP 参考:go/pkg/mod/github.com/gin-gonic/ginv1.7.7/gin.go:506 通过path找到…

Qt根据单价计算总价与进制转换

1.相关说明 二进制、十进制、十六进制间的相互转换 2.界面绘制 3.相关主要代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete …

学习JavaEE的日子 day12 构造方法 类的制作

Day12 需求:创建人类的对象,并操作对象 分析: 人类 - Person 属性:name、sex、age 方法:eat、sleep 场景:创建多个对象,去操作对象 //测试类:该类中有main方法,测试我们写…

进程切换和是Linux2.6内核中进程调度的算法

正文开始前给大家推荐个网站,前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 进程切换 进程并发就需要做到进程切换,一个CPU一套寄存器但是需要运行的进程有很多…

KT148A语音芯片智能锁扩展语音地址以及如何支持大量小文件的打包

一、语音芯片应用于智能锁的需求 智能锁的语音播放需求中,有很多需要多国语言合并在一起的需求 其中语音文件数多,并且每个语音文件小的特点 如果使用OTP的语音芯片,就很麻烦,因为用户不可烧录,调试也很繁琐 同时大…

μ综合设计控制器

μ综合设计控制器是一种基于μ分析的控制器设计方法,用于提高控制器的鲁棒性和性能。μ分析是一种数学工具,用于描述和比较控制系统在不同参数变化下的性能。通过μ综合设计,可以综合运用各种控制策略,以达到更好的控制效果。 μ…

pycharm debug显示的变量过多

问题: https://blog.csdn.net/Hodors/article/details/117535731 解决方法: 把"Show console variables by default"前面的勾取消掉就行 参考: https://stackoverflow.com/questions/48969556/hide-console-variables-in-pychar…

C语言--质数算法和最大公约数算法

文章目录 1.在C语言中,判断质数的常见算法有以下几种:1.1.试除法(暴力算法):1.2.优化试除法:1.3.埃拉托色尼筛法:1.4.米勒-拉宾素性检验:1.5.线性筛法:1.6.费马小定理&am…

k8s---配置资源管理

目录 配置资源管理的方式 secret pod如何来引用secret??? 陈述式创建: 声明式创建 Secret创建加密文件 使用token挂载 环境变量使用 docker-registry ConfigMap 陈述式 热更新 总结: 配置资源管理的方式 …

OJAC近屿智能带你解读:AIGC必备知识之Lang Chain

Look!👀我们的大模型商业化落地产品📖更多AI资讯请👉🏾关注Free三天集训营助教在线为您火热答疑👩🏼‍🏫 Lang Chain, 是一种先进的语言模型链技术,旨在通过串联多个专业…

js逆向第21例:猿人学第20题新年挑战

文章目录 一、前言二、定位加密参数1、定位wasm加密2、反编译wasm3、定位sign加密三、代码实现四、参考文献一、前言 新春福利:抓取这5页的数字,计算加和并提交结果 二、定位加密参数 通过get请求地址可以看到需要搞定参数有page、sign、t如下图: 进入堆栈不难发现这样一…

互联网加竞赛 基于机器视觉的12306验证码识别

文章目录 0 简介1 数据收集2 识别过程3 网络构建4 数据读取5 模型训练6 加入Dropout层7 数据增强8 迁移学习9 结果9 最后 0 简介 🔥 优质竞赛项目系列,今天要分享的是 基于机器视觉的12306验证码识别 该项目较为新颖,适合作为竞赛课题方向…

驾驭车联网的力量:深入车联网网络架构

车联网,作为移动互联网之后的新风口,以网联思想重新定义汽车,将其从简单的出行工具演化为个人的第二空间。车联网涵盖智能座舱和自动驾驶两大方向,构建在网联基础上,犀思云多年深度赋能汽车行业,本文将从车…

极端恶劣天气数据集-

极端恶劣天气数据集是一个包含了各种极端天气事件的统计信息的数据集。这些事件包括暴雨、暴雪、台风、龙卷风等极端天气现象。该数据集提供了有关这些极端天气事件的时间、地点、持续时间、强度等详细信息。 这个数据集对于研究和分析极端天气现象的频率、趋势和影响具有重要…

基于K-Means聚类与RFM模型分析顾客消费情况【500010102】

项目说明 本数据集是生成式模拟数据,本项目通过可视化分析对数据进行初步探索,再通过时间序列针对店铺的销售额进行分析,对时序图进行分解,发现数据存在季节性,并且通过auto_arima自动选择参数建立了SARIMA模型&#…

【Leetcode 程序员面试金典 02.08】 —— 环路检测 |双指针

面试题02.08. 环路检测 给定一个链表,如果它是有环链表,实现一个算法返回环路的开头节点。若环不存在,请返回null。 如果链表中有某个节点,可以通过连续跟踪next指针再次到达,则链表中存在环。 为了表示给定链表中的…