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高效获取数据的数据结构(有序)。在数据之外,数据 库系统还维护者满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就可以在这些数 据…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...

(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...