go语言基础--面向对象杂谈

面向过程

所谓的面向过程就是:强调的是步骤、过程、每一步都是自己亲自去实现的。

面向对象

所谓的面向对象其实就是找一个专门做这个事的人来做,不用关心具体怎么实现的。
所以说,面向过程强调的是过程,步骤。而面向对象强调的是对象,也就是干事的人。
在程序中,可以通过属性和方法(函数)来描述类。属性就是特征,方法(函数)就是行为。

面向对象编程好处

封装
继承
多态

继承

继承是一种类间关系,描述一个类从另一个类获取成员信息的类间关系。
继承必定发生在两个类之间,参与继承关系的双方称为父类和子类。
父类提供成员信息,子类获取成员信息。
通过匿名字段来实现继承
在这里插入图片描述

package mainimport "fmt"type Student struct {//属性---成员//方法---函数Person //匿名字段,只有类型,没有成员的名字score float64
}type Teacher struct {Person //匿名字段,只有类型,没有成员的名字salary float64
}type Person struct {id   intname stringage  int
}func main() {var stu Student = Student{Person{1, "张三", 18}, 98}fmt.Println(stu) //{{1 张三 18} 98}//部分初始化var stu1 Student = Student{score: 90}fmt.Println(stu1) //{{0  0} 90}var stu2 Student = Student{Person: Person{id: 101}} //{{101  0} 0}fmt.Println(stu2)
}

成员操作

package mainimport "fmt"type Student struct {//属性---成员//方法---函数Person //匿名字段,只有类型,没有成员的名字score float64
}type Person struct {id   intname stringage  int
}func main() {var stu Student = Student{Person{101, "张三", 18}, 98}var stu1 Student = Student{Person{102, "李四", 18}, 80}//获取成员的值fmt.Println(stu.score)      //98fmt.Println(stu1.score)     //80fmt.Println(stu1.Person.id) //102 //比较麻烦fmt.Println(stu1.id)        //102//修改成员的值stu.score = 100fmt.Println(stu.score) //100}

指针类型匿名字段

package mainimport "fmt"type Student struct {//属性---成员//方法---函数*Person //指针类型匿名字段score float64
}type Person struct {id   intname stringage  int
}func main() {var stu Student = Student{&Person{101, "张三", 18}, 98}fmt.Println(stu)      //{0xc000054460 98} 父类输出的是结构体内存地址 只能使用成员操作了fmt.Println(stu.name) //张三
}

多重继承—尽量不要写多重继承

package mainimport "fmt"// Student 学生继承person
type Student struct {//属性---成员//方法---函数Person //指针类型匿名字段score float64
}// Person 父类 person继承object
type Person struct {Object1name stringage  int
}type Object1 struct {id int
}func main() {var stu Studentstu.age = 18fmt.Println(stu.Person.age) //18stu.id = 101fmt.Println(stu.Person.Object1.id)
}

为结构体添加方法—封装

func  (对象 结构体类型) 方法名 (参数列表)(返回值列表) {代码体}

方法调用

对象名.方法

//不支持重载,只要接收者类型不一样,这个方法就算同名,也是不同方法,不会出现重复定义函数的错误

package mainimport "fmt"// Student
type Student struct {id   intname stringage  int
}// PrintShow 方法 s为接收者
func (s Student) PrintShow() {fmt.Println(s) //{101 ziye 18}
}func (s Student) EditInfo() {s.age = 20
}func (s *Student) EditInfo1() {s.age = 20
}
func main() {stu := Student{101, "ziye", 18}//对象名.方法名 把stu中的值传给了sstu.PrintShow() //完成对方法的调用stu.EditInfo()  //不是引用传递,是值传递stu.PrintShow()//内部会进行转换stu.EditInfo1() //引用传递stu.PrintShow() //{101 ziye 20}
}

注意事项

只要接收者类型不一样,这个方法就算同名,也是不同方法
接收者为指针类型

package mainimport "fmt"// Student
type Student struct {id   intname stringage  int
}type Teacher struct {id   intname string
}func (s *Student) show() {fmt.Println(s)
}func (t *Teacher) show() { //把teacher内存地址给到这里fmt.Println(t)
}
func main() {//如果接收者类型不同,即使方法的名字是相同的也是不同的方法stu := Student{101, "ziye", 18}stu.show() //等价于(&stu).show()teacher := Teacher{102, "ziyeye"}teacher.show()
}

面向对象方法练习

定义一个学生类,有六个属性,分别为姓名、性别、年龄、语文、数学、英语成绩
定义两个方法:

第一方法:打招呼的方法:介绍自己叫XX,今年几岁了。是男同学还是女同学。
第二个方法:计算总分与平均分的方法
package mainimport "fmt"// Student
type StudentInfo struct {name    string  //姓名sex     string  //性别age     int     //年龄chinese float64 //语文math    float64 //数学english float64 //英语
}// SayHello 打招呼
func (studentInfo *StudentInfo) SayHello(username string, userAge int, userSex string) {//初始化studentInfo.name = usernamestudentInfo.age = userAgestudentInfo.sex = userSex//初始化后的值进行判断if studentInfo.sex != "男" && studentInfo.sex != "女" {studentInfo.sex = "男"}if studentInfo.age < 1 || studentInfo.age > 100 {studentInfo.age = 18}//打印输出结果fmt.Printf("我叫%s,年龄是%d,性别是%s\n", studentInfo.name, studentInfo.age, studentInfo.sex)
}// GetScore 计算平均分
func (studentInfo *StudentInfo) GetScore(chinese float64, math float64, english float64) {//初始化studentInfo.chinese = chinesestudentInfo.math = mathstudentInfo.english = english//进行计算sum := studentInfo.chinese + studentInfo.math + studentInfo.english//打印输出结果fmt.Printf("我叫%s,总分%f,平均分%.2f\n", studentInfo.name, sum, sum/3)
}
func main() {var stu StudentInfostu.SayHello("ziye", 18, "女")stu.GetScore(98, 97, 95)
}

方法继承

package mainimport "fmt"// Student
type Student struct {Personscore float64
}type Person struct {id   intname string //姓名age  int    //年龄
}func (p *Person) PrintInfo() {fmt.Println(*p) //{101 张三 18}
}func main() {stu := Student{Person{101, "张三", 18}, 90}//子类可以调用父类的方法stu.PrintInfo()
}

方法继承的练习

根据以下信息,实现对应的继承关系

记者:我叫张三 ,我的爱好是偷拍,我的年龄是34,我是一个男狗仔。

程序员:我叫孙全,我的年龄是23,我是男生,我的工作年限是 3年。

  package mainimport "fmt"// Person 定义父类
type Person struct {name stringage  intsex  string
}// SetValue 给父类添加方法
func (p *Person) SetValue(userName string, userAge int, userSex string) {p.name = userNamep.age = userAgep.sex = userSex
}// Rep 定义相应的子类 记者类
type Rep struct {PersonHobby string //爱好
}// Pro 程序员类
type Pro struct {PersonWorkYear int
}// RepSayHello 给子类添加相应的信息
func (r *Rep) RepSayHello(Hobby string) {r.Hobby = Hobbyfmt.Printf("我叫%s ,我的爱好是%s,我的年龄是%d,我是一个%s狗仔\n", r.name, r.Hobby, r.age, r.sex)
}// ProSayHello 给子类添加相应的信息
func (p *Pro) ProSayHello(workYear int) {p.WorkYear = workYearfmt.Printf("我叫%s,我的年龄是%d,我是%s,我的工作年限是 %d年\n", p.name, p.age, p.sex, p.WorkYear)
}
func main() {var rep Reprep.SetValue("ziye", 34, "男")rep.RepSayHello("偷拍")var pro Propro.SetValue("李四", 26, "男")pro.ProSayHello(3)}

方法重写

就是子类(结构体)中的方法,将父类中的相同名称的方法的功能重新给改写了
注意:在调用时,默认调用的是子类中的方法

package mainimport "fmt"// Person 定义父类
type Person struct {name stringage  int
}func (p *Person) PrintInfo() {fmt.Println("这是父类中的方法")
}type Student struct {Personscore float64
}func (s *Student) PrintInfo() {fmt.Println("这是子类中的方法")
}func main() {var stu Studentstu.PrintInfo() //这是子类中的方法 如果父类中的方法名称与子类中的方法一致,那么通过子类的对象调用的是子类中的方法,方法重写stu.Person.PrintInfo() //这是父类中的方法 调用父类中的方法
}

方法值与方法表达式

package mainimport "fmt"// Person 定义父类
type Person struct {name stringage  int
}func (p *Person) PrintInfo() {fmt.Println(*p) //{ziye 18}
}func main() {per := Person{"ziye", 18}per.PrintInfo()//方法值f := per.PrintInfofmt.Printf("%T\n", f) //func() 方法类型f()                   //{ziye 18}//方法表达式f1 := (*Person).PrintInfo //并没有指定一个对象 类名要和方法接收者类型保存一致f1(&per)                  //{ziye 18} 方法表达式
}

接口简介

接口就是一种规范与标准,只是规定了要做哪些事情。具体怎么做,接口是不管的。
接口把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实
现了这个接口。

接口定义

type 接口名字 interface {

方法声明

}

接口的声明

可以为结构体添加接口中的方法,完成接口中方法实现

package mainimport "fmt"// Personer 接口的声明
type Personer interface {SayHello() //方法声明
}type Student struct {
}// SayHello 使用student完成SayHello
func (s *Student) SayHello() {fmt.Println("老师好")
}type Teacher struct {
}func (t *Teacher) SayHello() {fmt.Println("学生好")
}func main() {//对象名.方法名var stu Studentstu.SayHello() //老师好var teacher Teacherteacher.SayHello() //学生好//接口变量来调用,必须都实现接口中所声明的方法var person Personerperson = &stuperson.SayHello() //调用的是Student、实现的SayHello方法 老师好person = &teacherperson.SayHello() //学生好}

多态的定义与实现

什么是多态

所谓多态:指的是多种表现形式。
多态就是同一个接口,使用不同的实例而执行不同操作

package mainimport "fmt"type Personer interface {SayHello()
}type Student struct {
}func (s *Student) SayHello() {fmt.Println("老师好")
}type Teacher struct {
}func (t *Teacher) SayHello() {fmt.Println("学生好")
}//实现多态
func WhoSayHi(personer Personer) {personer.SayHello()
}func main() {var stu Studentvar teacher TeacherWhoSayHi(&stu)WhoSayHi(&teacher)
}

案例

用多态来模拟实现 将移动硬盘或者U盘插到电脑上进行读写数据

package mainimport "fmt"type Stroager interface {Read()Writer()
}// MDisk 移动硬盘
type MDisk struct {
}func (m *MDisk) Read() {fmt.Println("移动硬盘读取数据")
}func (m *MDisk) Writer() {fmt.Println("移动硬盘写入数据")
}// UDisk U盘
type UDisk struct {
}func (u *UDisk) Read() {fmt.Println("U盘读取数据")
}func (u *UDisk) Writer() {fmt.Println("U盘写入数据")
}// Computer 定义一个函数
func Computer(s Stroager) {s.Writer()s.Read()
}
func main() {var uds UDiskvar mds MDiskComputer(&uds)Computer(&mds)
}

案例

使用面向对象方式,实现一个计算器程序

案例实现一


package mainimport "fmt"type Object1 struct {
}func (o *Object1) GetResult(num1, num2 int, op string) int {//添加参数var result intswitch op {case "+":result = num1 + num2case "-":result = num1 - num2}return result
}func main() {var obj Object1result := obj.GetResult(8, 6, "+")fmt.Println(result)
}

案例实现二

package mainimport "fmt"// 加法类
type Add struct {Object1
}func (add *Add) GetResult() int { //方法的实现要和接口中方法的声明保持一致return add.numA + add.numB
}type Sub struct {Object1
}func (sub *Sub) GetResult() int {return sub.numA - sub.numB
}type Object1 struct {numA intnumB int
}type Resulter interface {GetResult() int //返回类型int
}func main() {add := Add{Object1{10, 8}}result := add.GetResult()fmt.Println(result)sub := Sub{Object1{10, 8}}result = sub.GetResult()fmt.Println(result)
}

案例实现三

package mainimport "fmt"// 加法类
type Add struct {Object1
}func (add *Add) GetResult() int { //方法的实现要和接口中方法的声明保持一致return add.numA + add.numB
}type Sub struct {Object1
}func (sub *Sub) GetResult() int {return sub.numA - sub.numB
}type Object1 struct {numA intnumB int
}type Resulter interface {GetResult() int //返回类型int
}// OperatorFactory 对象创建问题
// 1:定义一个新的类
type OperatorFactory struct {
}// CreaeteOperator 创建一个方法,在该方法中完成对象的创建----封装
func (o *OperatorFactory) CreaeteOperator(op string, numA, numB int) int {switch op {case "+":add := Add{Object1{numA, numB}}return OperatorWho(&add)case "-":sub := Sub{Object1{numA, numB}}return OperatorWho(&sub)default:return 0}
}
// 多态
func OperatorWho(h Resulter) int {result := h.GetResult()return result
}
func main() {var operator OperatorFactorycreaeteOperator := operator.CreaeteOperator("+", 20, 10)fmt.Println(creaeteOperator)
}

接口的继承与转换

package mainimport "fmt"type Humaner interface {SayHello()
}// Personer 接口继承
type Personer interface {HumanerSay()
}
type Student struct {
}func (s *Student) SayHello() {fmt.Println("大家好")
}func (s *Student) Say() {fmt.Println("你好")
}func main() {var Stu Studentvar per Personerper = &Stuper.Say()per.SayHello() //可以调用所继承的接口中的方法//接口转换var h Humanerh = perh.SayHello()//超集可以转换为子集,反过来不可以//per = h
}

空接口定义与使用

var i interface{} //空接口
i = 123
fmt.Println(i)

空接口可以赋任意的类型,切片s可以赋值各种类型的

var s []interface{} //空接口切片ss = append(s, 123, "abc", 23.12)for i := 0; i < len(s); i++ {fmt.Println(s[i])}

空接口(interface{})不包含任何的方法,正因为如此,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值

类型断言

通过类型断言,可以判断空接口中存储的数据类型。
语法:value, ok := m.(T)
m:表空接口类型变量
T:是断言的类型
value: 变量m中的值。
ok: 布尔类型变量,如果断言成功为true,否则为false

package mainimport "fmt"func main() {var i interface{}i = 123value, ok := i.(int)if ok {fmt.Println(value)} else {fmt.Println("类型推断错误")}
}

案例–空接口与类型断言综合应用

计算器,完成数据校验

package mainimport "fmt"// 加法类
type Add struct {Object1
}func (add *Add) GetResult() int { //方法的实现要和接口中方法的声明保持一致return add.numA + add.numB
}func (add *Add) SetData(data ...interface{}) bool {//对数据的个数进行校验var b bool = trueif len(data) > 2 || len(data) <= 1 {fmt.Println("参数个数错误")b = false}value, ok := data[0].(int)if !ok {fmt.Println("第一个数类型错误")b = false}value1, ok1 := data[1].(int)if !ok1 {fmt.Println("第二个数类型错误")b = false}add.numA = valueadd.numB = value1//对传递过来的类型进行校验return b
}type Sub struct {Object1
}func (sub *Sub) GetResult() int {return sub.numA - sub.numB
}
func (sub *Sub) SetData(data ...interface{}) bool {//对数据的个数进行校验var b bool = trueif len(data) > 2 || len(data) <= 1 {fmt.Println("参数个数错误")b = false}value, ok := data[0].(int)if !ok {fmt.Println("第一个数类型错误")b = false}value1, ok1 := data[1].(int)if !ok1 {fmt.Println("第二个数类型错误")b = false}sub.numA = valuesub.numB = value1//对传递过来的类型进行校验return b
}type Object1 struct {numA intnumB int
}type Resulter interface {GetResult() int                   //返回类型intSetData(data ...interface{}) bool //完成参数运算的数据的类型校验
}// OperatorFactory 对象创建问题
// 1:定义一个新的类
type OperatorFactory struct {
}// CreaeteOperator 创建一个方法,在该方法中完成对象的创建----封装
func (o *OperatorFactory) CreaeteOperator(op string) Resulter {switch op {case "+":add := new(Add) //返回*addreturn addcase "-":sub := new(Sub) //创建Sub 开辟相应的存储空间return subdefault:return nil}
}// 多态
func OperatorWho(h Resulter) int {result := h.GetResult()return result
}
func main() {var operator OperatorFactorycreaeteOperator := operator.CreaeteOperator("-") //拿到对象setData := creaeteOperator.SetData(30, 10)if setData {who := OperatorWho(creaeteOperator)fmt.Println(who)}}

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

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

相关文章

【计算思维题】少儿编程 蓝桥杯青少组计算思维 数学逻辑思维真题详细解析第9套

蓝桥杯青少组计算思维 数学逻辑思维真题详细解析第9套 第十四届蓝桥杯省赛真题 1、要把下面4张图片重新排列成蜗牛的画像,该如何排列这些图片 A、 B、 C、 D、 答案:A 考点分析:主要考查小朋友们的观察能力空

向量的概念、向量组的概念

目录 向量的概念、向量组的概念 向量的基本运算 线性表出、线性相关、线性无关 向量的概念、向量组的概念 向量&#xff08;Vector&#xff09;是一个有次序的数所组成的数组&#xff0c;通常用来表示一个物理量或者一个对象在空间中的移动。向量可以表示位置、速度、力等物…

SpringMVC之文件上传下载以及jrebel的使用

目录 一.文件上传 1.1.导入依赖 1.2.配置文件上传解析器 ​​​​​​​ 1.3 配置服务器存放文件地址 1.3.1.点击编辑Configurations 1.3.2.将项目部署至tomcat服务器上 1.3.3.配置相对路径 1.4.导入PropertiesUtil工具类 1.5.编写resource.properties 1.6.添加sql 1.7.编写…

【C语言】扫雷小游戏(保姆教程)

目录 一、扫雷游戏介绍 二、代码分装 三、代码实现步骤 1. 制作菜单menu函数以及游戏运行逻辑流程 2. 数组棋盘分析 3. 创建棋盘数组 4. 初始化棋盘InitBoard函数 5. 显示棋盘DisplayBoard函数 6. 布置雷SetMine函数 7. 统计雷个数GetMineCount函数 8. 排查雷FindMine函…

算法分析与设计编程题 动态规划

矩阵连乘 题目描述 解题代码 void printOptimalParens(vector<vector<int>>& partition, int i, int j) {if (i j) cout << "A" << i; // 单个矩阵&#xff0c;无需划分else {cout << "(";printOptimalParens(partit…

网络安全中的欺骗攻击与防御技术

在Internet上计算机之间相互进行的交流建立在两个前提之下&#xff1a;认证、信任。 认证是网络上的计算机用于相互间进行识别的一种鉴别过程&#xff0c;经过认证的过程&#xff0c;获准相互交流的计算机之间就会建立起相互信任的关系。信任和认证具有逆反关系&#xff0c;即…

爬虫逆向实战(33)-某联社数据(webpack)

一、数据接口分析 主页地址&#xff1a;某联社 1、抓包 通过抓包可以发现数据接口是/nodeapi/telegraphList 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现有一个sign加密参数 请求头是否加密&#xff1f; 无 响应是否加密&#x…

性能监控-grafana+prometheus+node_exporter

Prometheus是一个开源的系统监控和报警工具。它由SoundCloud开发并于2012年发布&#xff0c;后来成为了一个独立的开源项目&#xff0c;并得到了广泛的应用和支持。 Prometheus的主要功能包括采集和存储各种系统和应用程序的监控数据&#xff0c;并提供强大的查询语言PromQL来…

【云原生】kubectl常用命令大全

目录 一、资源管理方法 kubectl 的命令大全 二、 kubectl常用命令大全 2.2 项目的生命周期&#xff1a;创建-->发布-->更新-->回滚-->删除 1、创建 kubectl create命令 2、发布 kubectl expose命令 3、更新 kubectl set 4、回滚 kubectl rollou…

线性代数的本质(九)——二次型与合同

文章目录 二次型与合同二次型与标准型二次型的分类度量矩阵与合同 二次型与合同 二次型与标准型 Grant&#xff1a;二次型研究的是二次曲面在不同基下的坐标变换 由解析几何的知识&#xff0c;我们了解到二次函数的一次项和常数项只是对函数图像进行平移&#xff0c;并不会改变…

Qt 围炉札记

文章目录 一、Qt 调试二、vscode 与 Qt1、安装插件&#xff1a;2、设置中配置插件 一、Qt 调试 【Qt调试技巧】Profile配置使用及一些坑 QT运行时的Debug、Release、Profile选项区别 Qt Creator release版本进行调试 【Qt调试技巧】如何在Release下调试Qt程序&#xff1f; …

STM32 CAN使用记录:bxCAN基础通讯

文章目录 目的关键配置与代码轮询方式中断方式收发测试 示例链接总结 目的 CAN是非常常用的一种数据总线&#xff0c;被广泛用在各种车辆系统中。这篇文章将对STM32中CAN的使用做个示例。 CAN的一些基础介绍可以参考下面文章&#xff1a; 《CAN基础概念》https://blog.csdn.n…