Go 面向对象(方法)

一、 概述

在面向对象编程中,一个对象其实也就是一个简单的值或者一个变量,在这个对象中会包含一些函数,这种带有接收者的函数,我们称为方法(method)。本质上,一个方法则是一个和特殊类型关联的函数。

一个面向对象的程序会用方法来表达其属性和对应的操作,这样使用这个对象的用户就不需要直接去操作对象,而是借助方法来做这些事情。

在Go语言中,可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法。

⽅法总是绑定对象实例,并隐式将实例作为第⼀实参 (receiver),方法的语法如下:

func (receiver ReceiverType) funcName (parameters) (results)
  • 参数 receiver 可任意命名。如⽅法中未曾使⽤,可省略参数名。
  • 参数 receiver 类型可以是 T 或 *T。基类型 T 不能是接⼝或指针。
  • 不支持重载方法,也就是说,不能定义名字相同但是不同参数的方法。

二、 为类型添加方法

1. 基础类型作为接收者

// 自定义类型,给int改名为MyInt
type MyInt int// 在函数定义时,在其名字之前放上一个变量,即是一个方法
func (a MyInt) Add(b MyInt) MyInt {return a + b
}//传统方式的定义
func Add(a, b MyInt) MyInt {//面向过程return a + b
}func main() {var a MyInt=1var b MyInt=1//调用func (aMyInt) Add(bMyInt)fmt.Println("a.Add(b)=",a.Add(b))//a.Add(b)=2//调用func Add(a,bMyInt)fmt.Println("Add(a,b)=",Add(a,b))//Add(a,b)=2
}

通过上面的例子可以看出,面向对象只是换了一种语法形式来表达。方法是函数的语法糖,因为receiver其实就是方法所接收的第1个参数。

注意:虽然方法的名字一模一样,但是如果接收者不一样,那么方法就不一样。

2. 结构体作为接收者
方法里面可以访问接收者的字段,调用方法通过点.访问,就像`struct``里面访问字段一样:

type Person struct {name stringsex byteage int
}func (p Person) PrintInfo(){//给Person添加方法fmt.Println(p.name,p.sex,p.age)
}func main() {p:=Person{"mike",'m',18}//初始化p.PrintInfo()//调用func(pPerson)PrintInfo()
}

打印结果为mike,m,18,你方法写的是Person那么这个方法只能传Person,不能传别的类型。

type student struct { //学生name stringsex  stringage  int
}func (s student) Print() {s.age = 10fmt.Println(s)
}
func main() {stu := student{"赵云", "男", 30}stu.Print()fmt.Println(stu)
}{赵云 男 10}
{赵云 男 30}

三、 值语义和引用语义

type Person struct {name stringsex byteage int
}// 指针作为接收者,引用语义
func (p *Person) SetInfoPointer(){// 给成员赋值(*p).name = "yoyo"p.sex = 'f'p.age = 22
}// 值作为接收者,值语义
func (p Person) SetInfoValue(){// 给成员赋值p.name = "yoyo"p.sex = 'f'p.age = 22
}func main() {// 指针作为接收者,引用语义p1 := Person{"mike",'m',18} // 初始化fmt.Println("函数调用前=",p1) // 函数调用前={mike10918}(&p1).SetInfoPointer()fmt.Println("函数调用后=",p1) // 函数调用后={yoyo10222}fmt.Println("==========================")p2 := Person{"mike",'m',18} // 初始化// 值作为接收者,值语义fmt.Println("函数调用前=",p2) // 函数调用前={mike10918}p2.SetInfoValue()fmt.Println("函数调用后=",p2) // 函数调用后={mike10918}
}

四、方法集

类型的方法集是指可以被该类型的值调用的所有方法的集合。

用实例实例value和pointer调用方法(含匿名字段)不受⽅法集约束,编译器编总是查找全部方法,并自动转换receiver实参。

1.类型*T方法集
一个指向自定义类型的值的指针,它的方法集由该类型定义的所有方法组成,无论这些方法接受的是一个值还是一个指针。

如果在指针上调用一个接受值的方法,Go语言会聪明地将该指针解引用,并将指针所指的底层值作为方法的接收者。

类型*T⽅法集包含全部receiver T + *T⽅法:

type Person struct{name stringsex byteage int
}// 指针作为接收者,引用语义
func (p *Person) SetInfoPointer(){(*p).name="yoyo"p.sex='f'p.age=22
}// 值作为接收者,值语义
func (p Person) SetInfoValue(){p.name="xxx"p.sex='m'p.age=33
}func main() {// p为指针类型var p*Person = &Person{"mike",'m',18}p.SetInfoPointer() // func (p)SetInfoPointer()p.SetInfoValue() // func (*p)SetInfoValue()(*p).SetInfoValue() // func (*p)SetInfoValue()
}

2. 类型T方法集
一个自定义类型值的方法集则由为该类型定义的接收者类型为值类型的方法组成,但是不包含那些接收者类型为指针的方法。

但这种限制通常并不像这里所说的那样,因为如果我们只有一个值,仍然可以调用一个接收者为指针类型的方法,这可以借助于Go语言传值的地址能力实现。

package mainimport "fmt"type Student struct {name stringage int
}// 指针作为接收者 引用语义
func (s *Student) SetStuPointer() {s.name = "Bob"s.age = 18
}// 值作为接收者 值语义
func (s Student) SetStuValue() {s.name = "Peter"s.age = 18
}func main() {// 指针作为接收者,引用语义s1 := Student{"Miller", 18} // 初始化fmt.Println("函数调用前 = ", s1) // 函数调用前 = {Miller 18}(&s1).SetStuPointer()fmt.Println("函数调用后 = ", s1) // 函数调用后 = {Bob 18}fmt.Println("==========================")s2 := Student{"mike", 18} // 初始化//值 作为接收者,值语义fmt.Println("函数调用前 = ", s2) // 函数调用前 = {mike 18}s2.SetStuValue() fmt.Println("函数调用后 = ", s2) // 函数调用后 = {mike 18}
}
// 总结 : (引用语义:会改变结构体内容) (值语义:不会改变结构体内容)

五、 匿名字段

1. 方法的继承
如果匿名字段实现了一个方法,那么包含这个匿名字段的struct也能调用该方法。

type Person struct {name stringsex byteage int
}//Person定义了方法
func (p *Person) PrintInfo() {fmt.Printf("%s,%c,%d\n",p.name,p.sex,p.age)
}type Student struct {Person//匿名字段,那么Student包含了Person的所有字段id intaddr string
}func main() {p := Person{"mike",'m',18}p.PrintInfo()s := Student{Person{"yoyo",'f',20},2,"sz"}s.PrintInfo()
}

也就是说我用student继承了person那么我就拥有了person的一切不管是字段,还是方法,我都能调用。

子类可以继承父类 可以继承属性和方法,但是父类不可继承子类的

// 子类
type student01 struct {studentclass int
}func (s *student) PrintInfo() {fmt.Printf("编号%d\n", s.id)fmt.Printf("姓名%s\n", s.name)fmt.Printf("年龄%d\n ", s.age)
}
func main() {s := student{"赵云", 110, 30}s.PrintInfo()// 子类可以继承父类  可以继承属性和方法s1 := student01{student{"李白", 100, 20}, 9}s1.PrintInfo()
}

2. 方法的重写

type Person struct {name stringsex byteage int
}
//Person定义了方法
func (p *Person) PrintInfo() {fmt.Printf("Person:%s,%c,%d\n",p.name,p.sex,p.age)
}
type Student struct {Person//匿名字段,那么Student包含了Person的所有字段id intaddr string
}
//Student定义了方法
func (s *Student) PrintInfo() {fmt.Printf("Student:%s,%c,%d\n",s.name,s.sex,s.age)
}func main() {p:=Person{"mike",'m',18}p.PrintInfo() //Person:mike,m,18s:=Student{Person{"yoyo",'f',20},2,"sz"}s.PrintInfo() //Student:yoyo,f,20s.Person.PrintInfo() //Person:yoyo,f,20
}

也就是说我调用了Person的方法,但是我觉得这个方法不行,然后我自己又重新写了个方法,最后调用student方法的时候就只会调用我这个方法,而不会调用person的方法了

六、 方法值和方法表达式

类似于我们可以对函数进行赋值和传递一样,方法也可以进行赋值和传递。

根据调用者不同,方法分为两种表现形式:方法值和方法表达式。两者都可像普通函数那样赋值和传参,区别在于方法值绑定实例,⽽方法表达式则须显式传参。

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

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

相关文章

vue3+ts+uniapp实现小程序端input获取焦点计算上推页面距离

vue3tsuniapp实现小程序端input获取焦点计算上推页面距离 input获取焦点计算上推页面距离 1.先说我这边的需求2.发现问题3.解决思路4.代码展示 自我记录 1.先说我这边的需求 需求 1.给键盘同级添加一个按钮例如’下一步’ or ‘确认’ 这种按钮 2.初步想法就是获取input焦点时…

【LeetCode-中等题】146. LRU 缓存

文章目录 题目方法一:直接继承LinkedHashMap调用api方法二:自定义LinkedHashMap HashMap ListNode LinkedHashMap 题目 LRU缓存是什么:LRU缓存机制,你想知道的这里都有 实现 LRU 缓存算法 方法一:直接继承Linked…

单臂路由实验:通过Trunk和子接口实现VLAN互通

文章目录 一、实验背景与目的二、实验拓扑三、实验需求四、实验解法1. PC 配置 IP 地址2. PC3 属于 Vlan10,PC4 属于 Vlan20,配置单臂路由实现 Vlan10 和 Vlan20 三层互通3. 测试在 PC3 上 Ping PC4 ,可以 Ping 通 PC4 摘要: 本文…

数学建模:回归分析

🔆 文章首发于我的个人博客:欢迎大佬们来逛逛 数学建模:回归分析 文章目录 数学建模:回归分析回归分析多元线性回归案例 多项式回归一元多项式回归多元二项式回归 非线性回归逐步回归 回归分析 多元线性回归 案例 首先进行回归分…

ASP.NET Core 中的 MVC架构

MVC 架构 MVC架构把 App 按照逻辑分成三层: Controllers,接收 http request,配合 model,通过http response 返回 view,尽量不做别的事Models, 负责业务逻辑,App 的状态,以及数据处理Views&…

JVM的故事——虚拟机字节码执行引擎

虚拟机字节码执行引擎 文章目录 虚拟机字节码执行引擎一、概述二、运行时栈帧结构三、方法调用 一、概述 执行引擎Java虚拟机的核心组成之一,它是由软件自行实现的,能够执行那些不被硬件直接支持的指令集格式。 对于不同的虚拟机实现,执行引…

【网络安全带你练爬虫-100练】第20练:数据处理-并写入到指定文档位置

目录 一、目标1:解码去标签 二、目标2:提取标签内内容 三、目标3:处理后的数据插入原位置 四、目标4:将指定的内容插入指定的位置 五、目标5:设置上下文字体格式 六、目标6:向多个不同位置插入不同的…

企业如何充分借助大数据下精准营销?

技术的发展和智能终端的普及移动互联网用户的大规模增长使移动互联网快速发展,使中国移动互联网软件进入移动互联网时代越来越多地涉及到改变生活大家习惯。移动互联网时代的到来也意味着大数据时代的到来。精准营销数据方法,移动互联网和大数据的兴起不…

ZLMediaKit 重建docker包

1.下载容器到本地服务器并运行 #此镜像为github持续集成自动编译推送,跟代码(master分支)保持最新状态 docker run -id -p 1935:1935 -p 8080:80 -p 8443:443 -p 8554:554 -p 10000:10000 -p 10000:10000/udp -p 8000:8000/udp -p 9000:9000/udp zlmediakit/zlmedi…

vue 实现在线预览word文档

使用插件: docxx npm实现在线预览word文档 官网:npm参数 项目使用: reViewFile_2(){let body {"distCodes": [],"startDate": "","endDate": "","county": ""}thi…

App自动化测试持续集成效率提高50%

持续集成是一种开发实践,它倡导团队成员需要频繁的集成他们的工作,每次集成都通过自动化构建(包括编译、构建、自动化测试)来验证,从而尽快地发现集成中的错误。让正在开发的软件始终处于可工作状态,让产品…

PostgreSQL 备份恢复:pg_probackup

文章目录 前言1. 安装备份工具1.1 环境介绍1.2 RPM 安装1.3 验证 2. 配置备份工具2.1 初始化设置2.2 创建备份用户2.3 配置自动归档 3. 工具使用介绍3.1 init3.2 add-instance3.3 del-instance3.4 set-config3.5 show-config3.6 set-backup3.7 backup3.8 show3.9 delete3.10 re…

拦截器和异常处理器

拦截器和异常处理器 拦截器 拦截器(Interceptor)&#xff0c;主要完成请求参数的解析、将页面表单参数赋给值栈中相应属性、执行功能检验、程序异常调试等工作。 准备 创建模块 如下为完整的项目结构 web.xml <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee&qu…

macos 不支持svn安装

macos 10.13可能不支持svn命令,所以要安装 xcode-select --install 弹窗在线安装失败的话只能手动下载安装 打开:Sign In - Apple 搜索Command Line Tools (macOS 10.13) 下载9.4.1版本直接安装后即可

利用vba处理Excel表格数据实现键值转化,适用于将编码转化成对应的文本

最近遇到了一个甲方需要提供系统登录的用户名单和对应的角色权限内容。无奈直接从数据库导出的数据对应的都是编码&#xff0c;没有转成中文&#xff0c;想着偷个懒能不能直接用Excel直接转&#xff0c;网上看了一下有修改单元格格式的&#xff0c;但需要编码是2到3个。多的就用…

基于量子密钥分发和区块链技术的新一代加密通信系统

量子通信与区块链构建下一代加密通信基础设施 量子技术和区块链技术是国家信息安全和国家数字化转型的重要组成部分&#xff0c;在国家战略中具有重要地位。“十四五”规划纲要将“加快数字发展建设数字中国”作为独立篇章&#xff0c;指出要进一步明确发展云计算、大数据、物联…

TCP机制之连接管理(三次握手和四次挥手详解)

TCP的连接管理机制描述了连接如何创建以及如何断开! 建立连接(三次握手) 三次握手的过程 所谓建立连接就是通信双方各自要记录对方的信息,彼此之间要相互认同;这里以A B双方确立男女朋友关系为例: 从图中可以看出,通信双方各自向对方发起一个"建立连接"的请求,同时…

RK3568-i2c-适配8010rtc时钟芯片

硬件连接 从硬件原理图中可以看出&#xff0c;rtc时钟芯片挂载在i2c3总线上&#xff0c;设备地址需要查看芯片数据手册。编写设备树 &i2c3 {status "okay";rx8010: rx801032 {compatible "epson,rx8010";reg <0x32>;}; };使能驱动 /kernel/…

Redis布隆过滤器原理

其实布隆过滤器本质上要解决的问题&#xff0c;就是防止很多没有意义的、恶意的请求穿透Redis&#xff08;因为Redis中没有数据&#xff09;直接打入到DB。它是Redis中的一个modules&#xff0c;其实可以理解为一个插件&#xff0c;用来拓展实现额外的功能。 可以简单理解布隆…

【闭源期刊】Elsevier旗下,1区(TOP),3个月录用

闭源期刊 1区&#xff08;TOP&#xff09; 出版社&#xff1a;Elsevier 影响因子&#xff1a;IF&#xff08;2022&#xff09;8.5-9.0 期刊分区&#xff1a;JCR1区&#xff0c;中科院2区&#xff08;无预警记录&#xff09; 检索情况&#xff1a;SCIE&EI 双检&#xff…