Go 语言学习-3

Go 语言学习-3

面向对象

结构体
支持面向对象编程  并不是纯粹的面向对象语言 没有类的概念 代之为结构体。
没有构造函数 方法重载 隐藏this 指针
继承是通过匿名字段实现  通过接口关联 耦合性低。

结构体 结构体变量
结构体变量是值类型。代表一个具体变量
type 结构体名称 struct{
}
结构体 数据类型是指针 slice map 初始值都是nil 即还没分配空间
值拷贝 改变一个之后 另外一个不会随之变化
想要一起改变 :取地址 。

创建结构体 变量和访问结构体字段

SS187---结构体内存分配机制:
	可以 p2.Age 也可以(*p2).Age 但不可 *p2.Age :. 点的优先级更高
结构体中所有字段在内存中是连续分布的
如果是指针:
	本身地址是连续的 
	指向的地址可能不是连续的
func main() {
	var p1 Cat
	fmt.Println(p1)
	// 使用切片 map 时先make
	p1.slice = make([]int, 2)
	p1.dtr = make(map[string]string, 2)
	p1.dtr["add"] = "like"
	p1.dtr["adda"] = "likea"
	fmt.Println(p1)
	// 1
	var cat Dog
	//2
	cat1 := Dog{"mark", "12"}
	fmt.Println(cat, cat1)
	//3 new 出来的是一个指针
	var person *Dog = new(Dog)
	//(*person).Name = "Lisl"
	person.Name = "smics" //底层会进行处理
	(*person).Age = "oios"
	fmt.Println(*person)
	// 4
	var ps *Dog = &Dog{}
	ps.Age="2s"
	ps.Name="sld2"
	fmt.Println(*ps)
}

type Dog struct {
	Name string
	Age  string
}

type Cat struct {
	Name  string
	Age   int
	score [5]float32
	prt   *int
	slice []int
	dtr   map[string]string
}

两个结构体之间相互转换:
字段的名称 字段的个数 字段数据类型一致。
结构体进行type重新定义 相当于取别名 Go 认为是新的数据类型 但是相互之间可以强转。
结构体 字段上 可以写一个tag 该tag可以通过反射机制获取。 常见使用场景是序列化和反序列化。

type Mons struct {
	Name  string `json:"name"`
	Age   string `json:"age"`
	Skill string `json:"skill"`
}
	tag : for json   序列化的使用场景
方法

Go 中方法是作用在指定的数据类型上的 即和数据类型绑定 因此自定义类型 都可以有方法 不仅仅是struct
func (a A) test()
方法和类型绑定 只能通过类型调用 不能直接调用 也不能用其他变量类型调用。
在方法内改变 类对象的值 不会改变原对象的值 值拷贝。传地址可以改变 原对象。
方法的调用和传参机制。
通过变量通过方法调用时机制和函数是一样的。
调用方法 时该变量本身也会作为一个参数传递到方法中去。
值类型/引用类型。 值拷贝/地址拷贝。
执行 拷贝对象进栈 / 如果是指针则不用拷贝。
方法声明定义
func (receiver type) name(参数列表)(返回值列表){
方法体
return 返回值
}
receiver type:
表示这个方法 和type类型进行绑定 或者说该方法作用与type类型
type可以是结构体 也可以是其他自定义类型 tye integer int
receiver 就是type 类型的变量实例
结构体指针效率更高
如果一个类型实现了String() 这个方法 那么fmt.Println 会默认调用这个变量的String() 进行输出

方法和函数的区别
1)调用方式不一样
函数:函数名(实参列表)
方法:变量名.方法名(实参列表)
2)对于普通函数 接受者为值类型时 不能将指针类型的数据直接传递 反之亦然
3)对于方法 接受者为值类型时 可以直接用指针类型的变量调用方法 反之亦然
总结
1)不管调用形式如何 真正决定是值拷贝还是地址拷贝 是看这个方法是和哪个类型绑定
2)如果是和值类型则是值拷贝 如果是指针类型 则是地址拷贝。

面向对象编程 实例

工厂模式
Golang 结构体中没有构造函数 工厂模式解决这一问题
使用工厂模式 跨包创建结构体的案例
	结构体字段私有 则定义一个方法 来访问 Get。结构体指针类型的 Get 方法。

面向对象 【下】

Vscode 配置和快捷键。

封装
隐藏实现细节
提供对数据的验证 保证安全合理

体现封装:
对结构体的属性进行封装
通过方法 包实现封装。

继承
解决代码复用问题
	提高代码 复用性可扩展性。

1 结构体可以使用嵌套匿名结构体 所有的字段 和方法 即首字母大小写的字段 方法都可以使用
匿名字段访问可以简化
2 当结构体和匿名结构体有相同的字段或者方法时 编译器采用就近访问原则 如果希望访问匿名结构体的字段和方法 可以通过 匿名结构体名来。
3 结构体有的字段 不会访问匿名结构体 。
4 结构体里面嵌入两个 或多个 匿名结构体 。如在两个匿名结构体有相同的字段和方法(同时结构体本身没有同名字段和方法) 如在访问时 就必须明确指定 匿名结构体名字 否则编译报错。
5 如果一个struct 嵌套了一个有名的结构体 这种模式就是组合 如果是组合关系 那么在 访问组合的结构体的字段或方法时 必须带上结构体名字
6 嵌套匿名结构体后 也可以在 创建结构体变量 (实例)时 直接指定 各个匿名结构体字段的值。
2022-02-03

一个结构体中 int 类型的匿名字段只能有一个 。

多重继承
一个struct 嵌套了多个匿名结构体 那么该结构体 可以直接访问 嵌套匿名结构体的字段和 方法 从而实现 多重继承。
为了保证简洁性 尽量不使用多重继承。
接口
package main

import "fmt"

/**
接口
*/
func main() {
	c := Computer{}
	p := Phone{}
	cm := Camera{}
	c.Work(&p)
	c.Work(&cm)
}

type USB interface {
	//声明了两个没有实现的方法
	Start()
	Stop()
}
type Phone struct {
}

func (ph *Phone) Start() {
	fmt.Println("手机启动")
}

func (ph *Phone) Stop() {
	fmt.Println("手机关闭")
}

type Camera struct {
}

func (c *Camera) Start() {
	fmt.Println("相机启动")
}

func (c *Camera) Stop() {
	fmt.Println("相机关闭")
}

type Computer struct {
}

func (c Computer) Work(usb USB) { //方法接收接口类型 只要是实现接口的 实现USB接口:实现了USB接口声明
	usb.Start()
	usb.Stop()
}

接口:
接口里的所有方法没有方法体 即所有的方法都是没有实现的方法 接口体现了 程序设计的多态和高内聚 低耦合 的思想
Golang中的接口 不需要显式实现 只要一个变量 含有接口类型中的所有方法 那么这个变量就实现了这个接口 因此Golang中没有 implement 这样的关键字

接口的 注意事项 和细节
1.接口本身不能创建实例 但是可以指向一个实现了该接口的自定义类型的变量 实例

func main() {
	var stu Stu
	var a A = stu
	a.Say()
}

type A interface {
	Say()
}
type Stu struct {
	Name string
}

func (stu Stu) Say() {
	fmt.Println("Stu  Say()")
}
2.接口中所有的方法都没有方法体 即都是没有实现的方法
3.在Golang中需要将接口所有方法都实现 即是自定义类型实现了该接口

4.一个自定义类型只有实现了某个接口 才能将该自定义类型的实例 变量 赋给接口类型
5.只要是**自定义数据类型** 就可以实现接口 不仅仅是 结构体类型。

6 一个自定义类型可以实现多个接口
7 Golang 接口中 不能有任何变量
8 一个接口 比如A接口 可以继承多个别的借口 如BC 这时 如果要实现 A接口 也必须将BC接口的方法全部实现。

 9 interface 默认是一个指针 引用类型 如果没有 interface 初始化就是用那么会输出nil
10 空接口 interface{} 没有任何方法 所以所有类型都实现了空接口 

***可以把任何变量赋给空接口***
接口中不论来自多少个借口 但一定不能有相同的方法名。
注意:
	**方法实现是结构体指针实现的还是 结构体实现  即是绑定结构体指针还是绑定结构体。 ********

接口编程经典案例

	sort.Sort(data interface)
	**结构体切片排序。**

接口 和继承比较

实现接口在不破坏继承的前提下对结构体进行功能的扩展。
A结构体继承了B结构体 A结构体就自动的 继承了B结构体的字段和方法 并且可以直接使用 。
当A 需要扩展某个功能 同时不希望去破坏继承关系 则可以去实现某个接口即可。
实现接口是对继承机制的补充
规范性也可以得到保证
继承的价值在于 解决代码的复用性和 可维护性
接口的价值在于 设计 设计好各种规范 方法 让其他 自定义类型去实现 这些方法。
接口比继承更加灵活 继承是满足 is-a 关系 借口只需要满足like-a 关系
接口一定程度上 实现代码解耦。

多态

变量实例 具有多种形态 可以按照统一的接口来调用不同的实现 这时接口变量就呈现不同的形态
接口多态两种形式
—多态参数
—多态数组 。
2022-02-05

类型断言

类型断言

接口是一般类型 不知道具体类型 如果要转成具体类型 就需要使用类型断言

带检查的类型断言

项目实践

家庭收支 记账
客户信息管理系统

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值