go面向对象思想封装继承多态
go貌似都没有听说过继承,当然这个继承不像c++中通过class类的方式去继承,还是通过struct的方式,所以go严格来说不是面向对象编程的语言,c++和java才是,不过还是可以基于自身的一些的特性实现面向对象的功能,面向对象三大特性:封装、继承、多态
封装
属性
go是接住结构体struct
实现类的声明,比如要定义个学生类,学生类和animal类是面向对象示例介绍中重点,可以通过如下方式实现:
type Student struct {id uintname stringmale boolscore float64
}
结构体名或者说类名为 Student
,并且包含了 id
、name
、male
、score
四个属性,Go 语言中也不支持构造函数、析构函数,取而代之地,可以通过定义形如 NewXXX
这样的全局函数(首字母大写)作为类的初始化函数
func NewStudent(id uint, name string, male bool, score float64) *Student {return &Student{id, name, male, score}
}
在这个函数中,我们通过传入的属性字段对 Student 类进行初始化并返回一个指向该类的指针
在 Go 语言中,未进行显式初始化的变量都会被初始化为该类型的零值,例如 bool 类型的零值为 false,int 类型的零值为 0,string 类型的零值为空字符串,float 类型的零值为 0.0。接着就可以调用了
package main
import ("fmt"student2 "student/stu"
)
func main() {student := student2.NewStudent(1, "zhiyu",false, 100)fmt.Println(student)
}
成员函数
getXXX方法
要为 Go 类定义成员方法,需要在 func 和方法名之间声明方法所属的类型(有的地方将其称之为接收者声明),以 Student 类为例,要为其定义获取 name 值的方法,可以这么做:
func (s Student) GetName() string {return s.name
}
这样就可以使用GetName
方法获取name
属性,通过在函数签名中增加接收者声明的方式定义了函数所归属的类型,这个时候,函数就不再是普通的函数,而是类的成员方法了
setXXX方法
getName
是一个只读方法,setName
是一个可写的方法,所以需要使用指针的方式进行传参,在类的成员方法中,可以通过声明的类型变量来访问类的属性和其他方法
func (s *Student) SetName(name string) {s.name = name
}
可以把接收者类型为指针的成员方法叫做指针方法
,把接收者类型为非指针的成员方法叫做值方法
,二者的区别在于值方法传入的结构体变量是值类型(类型本身为指针类型除外),因此传入函数内部的是外部传入结构体实例的值拷贝,修改不会作用到外部传入的结构体实例.
另外,需要声明的是,在 Go 语言中,当我们将成员方法 SetName
所属的类型声明为指针类型时,严格来说,该方法并不属于 Student
类,而是属于指向 Student
的指针类型,所以,归属于 Student
的成员方法只是 Student
类型下所有可用成员方法的子集,归属于 *Student
的成员方法才是 Student
类完整可用方法的集合。
在调用值方法和指针方法时,需要记住以下两条准则:
- 值方法可以通过指针和值类型实例调用,指针类型实例调用值方法时会自动解引用;
- 指针方法只能通过指针类型实例调用,但有一个例外,如果某个值是可寻址的(或者说左值),那么编译器会在值类型实例调用指针方法时自动插入取地址符,使得在此情形下看起来像指针方法也可以通过值来调用
左值和右值
结合上面的两条准则使用示例说明如下:
package mainimport "fmt"
type Student struct {id uintname stringscore float64
}func NewStudent(id uint, name string, score float64) *Student {return &Student{id: id, name: name, score: score}
}func NewStudentV2(id uint, name string, score float64) Student {return Student{id: id, name: name, score: score}
}func (s Student) GetName() string {return s.name
}func (s *Student) SetName(name string) {s.name = name
}func main() {s := NewStudent(1, "zhiyu", 100)s.SetName("zhiyu-1") // ok 正常调用指针方法fmt.Println(s.GetName()) // ok 指针调用值方法自动解引用: (*s).GetName()s2 := NewStudentV2(2, "zhiyu", 90)s2.SetName("zhiyu-2") // ok s2 是可寻址的左值,所以实际调用: (&s2).SetName("zhiyu-2")fmt.Println(s2.GetName()) // ok 正常调用值方法NewStudent(3, "zhiyu", 80).SetName("zhiyu-3") // ok 正常调用指针方法NewStudentV2(4, "zhiyu", 99).SetName("zhiyu-4") // err 值类型调用指针方法
}
之所以可以直接在 s2
值实例上调用 SetName
指针方法,是因为 s2
是可寻址的,Go 语言底层会自动将 s2
转化为对应的指针类型 &s2
,所以真正调用的代码是 (&s2).SetName("zhiyu-2")
,而通过 NewStudentV2
(…)返回实例调用 SetName
时,则会报错,因为 NewStudentV2
(…) 是一个不可以寻址的右值。
所谓左值就是可以出现在赋值等号左边的值,而右值只能出现在赋值等号右边,比如函数返回值、字面量、常量值等。左值可寻址,右值不可寻址。
总结下来,就是一个自定义数据类型的方法集合中仅会包含它的所有「值方法」,而该类型对应的指针类型包含的方法集合才囊括了该类型的所有方法,包括所有「值方法」和「指针方法」,指针方法可以修改所属类型的属性值,而值方法则不能。
值方法|指针方法
有如下情形的考量时,需要将类方法定义为指针方法:
- 数据一致性:方法需要修改传入的类型实例本身;
- 方法执行效率:如果是值方法,在方法调用时一定会产生值拷贝,而大对象拷贝代价很大。
通常我们都会选择定义指针方法
继承
Go
虽然没有直接提供继承相关的语法实现,但是通过组合的方式间接实现类似功能,所谓组合,就是将一个类型嵌入到另一个类型,从而构建新的类型结构。使用了Student
类介绍封装,接着使用Animal
示例继承
package anitype Animal struct {Name string
}func (a Animal) Call() string {return "动物叫声"
}func (a Animal) FavorFood() string {return "爱吃的食物..."
}func (a Animal) GetName() string {return a.Name
}
所有的动物都有以上的三种方法,现在Dog
实现继承Animal
,新增一个dog.go,一般会给自家的爱狗起一个别名
package anitype Dog struct {AnimalAlias string
}func (d Dog) GetAliasName() string {return d.Alias
}
main.go
中如下所示
package mainimport ("animal/ani""fmt"
)func main() {animal := ani.Animal{"旺财"}dog := ani.Dog{animal, "旺旺"}fmt.Println(dog.GetName())fmt.Println(dog.Call())fmt.Println(dog.GetAliasName())
}
这就实现了继承的功能。注意在初始化子类时的顺序和struct中的定义顺序是一致的
多态
所谓多态就是一个函数的多种形态,比如在子类中定义同名函数来覆盖父类方法,专业属于称之为方法重写
。每个动物的喜欢吃的食物和叫声不同,这里实现下Dog
重写方法,在dog.go
中
package anitype Dog struct {AnimalAlias string
}func (d Dog) GetAliasName() string {return d.Alias
}func (d Dog) FavorFood() string {return "大棒骨"
}func (d Dog) Call() string {return "旺旺"
}
重写go build
,并在terminal中在animal
根目录下
当然子类也可以直接调用父类Animal
中的方法
fmt.Print(dog.Animal.Call())
fmt.Println(dog.Call())
fmt.Print(dog.Animal.FavorFood())
fmt.Println(dog.FavorFood())
相关文章:

go面向对象思想封装继承多态
go貌似都没有听说过继承,当然这个继承不像c中通过class类的方式去继承,还是通过struct的方式,所以go严格来说不是面向对象编程的语言,c和java才是,不过还是可以基于自身的一些的特性实现面向对象的功能,面向…...

【网络原理9】HTTP响应篇
在前两篇文章当中,已经分别介绍了HTTP是什么,以及常见的请求头当中的属性。【网络原理7】认识HTTP_革凡成圣211的博客-CSDN博客HTTP抓包,Fiddler的使用https://blog.csdn.net/weixin_56738054/article/details/129148515?spm1001.2014.3001.…...

SpringCloud之Seata(二)
4.Seata如何应用于项目? 安装seata及修改配置 4.1 官网下载Seata安装包 4.2 修改seata/config.txt 4.2.1 修改存储方式 store.db.dbTypemysql store.db.driverClassNamecom.mysql.jdbc.Driver store.db.urljdbc:mysql://你的IP:3306/seata?useUnicodetrue sto…...
【Redis-入门阶段】基本数据结构
Redis支持多种数据结构,包括字符串、列表、哈希、集合和有序集合。这些数据结构在Redis中被称为键值对,其中键是一个字符串,值可以是一个字符串、列表、哈希、集合或有序集合。接下来,我们将详细介绍这些数据结构的使用方法。字符…...

BACnet协议详解————MS/TP物理层,数据链路层和网络层
文章目录写在前面1 物理层2 数据链路层MSTP的流程如下noteMS/TP帧格式3 网络层写在前面 这周加更一篇,来弥补一下之前落下的进度。简单的说两句,之前讲应用层的时候,只是跟官方的手册来同步一下,但是从个人理解来说,自…...

Tomcat
Tomcat 1 简介 1.1 什么是Web服务器 Web服务器是一个应用程序(软件),对HTTP协议的操作进行封装,使得程序员不必直接对协议进行操作,让Web开发更加便捷。主要功能是"提供网上信息浏览服务"。 Web服务器是安…...

创客匠人直播:构建公域到私域的用户增长模型
进入知识付费直播带货时代,很多拥有知识技能经验的老师和培训机构吃到了流量红利。通过知识付费直播,老师们可以轻松实现引流、变现,还可以突破时间、地域的限制,为全国各地的学员带来优质的教学服务,因此越来越受到教…...

机试指南
文章目录零、绪论和IDE安装int取值范围常犯的编程小错误一、枚举和模拟 (暴力求解)(一) 枚举1.Reverse函数 求 反序数2.程序出错的原因1.编译错误 (compile):基本语法错误2.链接错误 (link):函数名写错了3.运行错误 (run):结果与预期不符&…...
Android CTA认证设定首选网络类型
需求 硬件只支持4G,过CTA认证时打网络电话,会出现3G网络的选择,会导致过不了,需要禁用3G网络选择功能。 Android 8.1.0 分析 可adb命令查看当前的网络类型 getprop | grep “network” 打印如下: [gsm.network.type]: [LTE,LTE] [ro.telephony.default_network]: [9] …...

Android 动态切换应用图标方案
经常听到大家讨论类似的需求,怀疑大厂是不是用了此方案,据我个人了解,多数头部 app 其实都是发版来更新节假日的 icon。当然本方案也是一种可选的方案,以前我也调研过,存在问题和作者所述差不多,此外原文链…...
SMART PLC斜坡函数功能块(梯形图代码)
斜坡函数Ramp的具体应用可以参看下面的文章链接: PID优化系列之给定值斜坡函数(PLC代码+Simulink仿真测试)_RXXW_Dor的博客-CSDN博客很多变频器里的工艺PID,都有"PID给定值变化时间"这个参数,这里的给定值变化时间我们可以利用斜坡函数实现,当然也可以利用PT1…...
不那么认真的linux复习
这是个不那么认真的linux总结,可能有一些错误 1、linuxkernel(内核)shell(外壳)fs(文件系统)pro/uti/tol(应用程序) 2、ls(列出文件) -a…...
Redis系列文章总纲
跟着老万学Redis 前言 从事开发工作这么久,很多核心技术其实都还只是局限在满足日常开发工作中的基础使用,并没有完整的总结研究。今年的目标之一是完成几个技术栈的系列博客,系统的总结一下知识体系,目前计划是从Redis开始。 Re…...

更新丨三大模块升级,助力高效交付商业项目!
功能更新!本文将介绍最新升级的步进漫游、行业方案、VR漫游三个模块,让您更快更好的了解系统能力,为您带来更加便捷、高效的使用体验。步进漫游 离线导出步进式漫游系统,是基于全景图自动生成三维建模的解决方案,实现大…...

C++回顾(二)——const和引用
2.1 C中的const 2.1.1 C与C中const的比较 (1)C语言中的const C语言中 const修饰的变量是一个 常变量,本质还是变量,有自己的地址空间。 (2)C中的const 1、C中 const 变量声明的是一个真正的常量ÿ…...
MXNet中使用双向循环神经网络BiRNN对文本进行情感分类<改进版>
在上一节的情感分类当中,有些评论是负面的,但预测的结果是正面的,比如,"this movie was shit"这部电影是狗屎,很明显就是对这部电影极不友好的评价,属于负类评价,给出的却是positive。…...

DNS 域名解析
介绍域名 网域名称(英语:Domain Name,简称:Domain),简称域名、网域。 域名是互联网上某一台计算机或计算机组的名称。 域名可以说是一个 IP 地址的代称,目的是为了便于记忆。例如,…...

Spring MVC 源码- ViewResolver 组件
ViewResolver 组件ViewResolver 组件,视图解析器,根据视图名和国际化,获得最终的视图 View 对象回顾先来回顾一下在 DispatcherServlet 中处理请求的过程中哪里使用到 ViewResolver 组件,可以回到《一个请求响应的旅行过程》中的 …...

【Hello Linux】初识冯诺伊曼体系
作者:小萌新 专栏:Linux 作者简介:大二学生 希望能和大家一起进步! 本篇博客简介:简单介绍冯诺伊曼体系 冯诺伊曼体系 冯诺伊曼体系结构的合理性 我们在Linux的第一篇博客中讲解了第一台计算机的发明是为了解决导弹的…...
mysql索引,主从多个核心主题去探索问题。
网上收集不错的优化方案 事务 mvcc 详讲 详讲 索引 索引概念 MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据 库系统还维护者满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就可以在这些数 据…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...

Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...