Golang学习之---面向“对象”编程(接口与多态)下(六)

一、抽象

把一类事物共有的属性(字段)行为(方法)提取出来,形成一个物理模型(结构体)。这种研究问题的方法称为抽象

二、封装encapsulation

封装就是把抽象出来的字段和对字段的操作封装在一起,数据被保护在内部,程序的其他包只有通过被授权的操作(方法),才能对字段进行操作。

2.1 封装的好处

  • ①隐藏实现细节,安全
  • ②可以对数据进行验证,保证安全合理(Age)

2.2 封装的实现步骤

  • ①将结构体、字段的首字母小写(不能导出了,类似于Java中的private)
  • ②给结构体所在包提供一个工厂模式的函数,首字母大写。类似一个构造函数
  • ③提供一个首字母大写的Set方法,用于对属性判断并赋值
  • ④提供一个首字母大写的Get方法,用于获取属性的值
  • 特别说明:在Golang开发中并没有特别强调封装,对OOP特性是做了简化处理的。这点不同于Java语言
    Golang学习之---面向“对象”编程(接口与多态)下(六)_第1张图片Golang学习之---面向“对象”编程(接口与多态)下(六)_第2张图片

三、继承

3.1 出现原因:
①小学生pupil,中学生,大学生graduate等结构体的字段和方法几乎相同,代码复用性不强
②代码冗余,而且代码不利于维护,也不利于功能扩展
③解决办法:通过继承方式来解决-》通过嵌套匿名结构体来实现
Golang学习之---面向“对象”编程(接口与多态)下(六)_第3张图片Golang学习之---面向“对象”编程(接口与多态)下(六)_第4张图片

3.2 深入讨论--细节

Golang学习之---面向“对象”编程(接口与多态)下(六)_第5张图片
对上面的代码总结:
1、当然直接通过b访问字段或方法时,其执行流程如下:
2、编译器会先看b对应的类型有没有Name,如果有,则直接调用B类型的Name字段
3、如果没有,就去看B中嵌入的匿名结构体A有没有Name字段,如果有,就调用,如果没有继续找...如果都找不到就报错

3.3 多重继承 

如果一个结构体嵌套了多个匿名结构体,那么该结构体可以直接访问嵌套匿名结构体的字段和方法,从而实现多重继承。

四、接口interface

Golang中多态特性主要是通过接口来体现的。
接口类型可以定义一组方法,不需要实现,而且接口中不能包含任何变量(Java接口里面可以包含变量)。到某个自定义类型要使用的时候,在根据具体情况把这些方法进行实现。

4.1 基本语法

Golang学习之---面向“对象”编程(接口与多态)下(六)_第6张图片
总结:
接口里所有的方法都没有方法体。接口体现了程序设计的多态和高内聚低耦合的思想。
② Golang的接口,不需要显式的实现,且没有implement关键字。只要一个变量含有接口类型中的所有方法,那么这个变量就实现了这个接口。

4.2 快速入门案例...

4.3 注意事项和细节

  • (1)接口本身不能创建实例,但可以指向一个实现了该接口的自定义类型的变量(实例)
    Golang学习之---面向“对象”编程(接口与多态)下(六)_第7张图片
  • (5)只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型
    Golang学习之---面向“对象”编程(接口与多态)下(六)_第8张图片

  • (8)一个接口如A可以继承多个接口如B和C,那么要实现A接口,也必须将B和C接口的方法全部实现

  • (9)接口类型默认是一个指针(引用类型),如果没有对接口初始化就使用,那么会输出nil

  • (10)空接口interface{}没有任何方法,所有所有类型都可以实现空接口。即我们可以把任何一个变量赋值给空接口

4.4 易错点
Golang学习之---面向“对象”编程(接口与多态)下(六)_第9张图片Golang学习之---面向“对象”编程(接口与多态)下(六)_第10张图片Golang学习之---面向“对象”编程(接口与多态)下(六)_第11张图片

4.5 实践--对自定义数据类型排序

Golang学习之---面向“对象”编程(接口与多态)下(六)_第12张图片Golang学习之---面向“对象”编程(接口与多态)下(六)_第13张图片
Golang学习之---面向“对象”编程(接口与多态)下(六)_第14张图片
Golang学习之---面向“对象”编程(接口与多态)下(六)_第15张图片
代码实现:
Golang学习之---面向“对象”编程(接口与多态)下(六)_第16张图片Golang学习之---面向“对象”编程(接口与多态)下(六)_第17张图片

4.6 接口VS继承

package main
import (
	"fmt"
)

// 结构体
type Monkey struct {
	Name string
}
func (this *Monkey) Climbing() {
	fmt.Println(this.Name, "生来会爬树")
}

// 接口
type BirdAble interface {
	Flying()
}
type FishAble interface {
	Swimming()
}

// 新的结构体
type LittleMonkey struct {
	Monkey // 继承了Monkey接口
}
// LittleMonkey实现了上面两个接口
func (this *LittleMonkey) Flying() {
	fmt.Println(this.Name, "通过学习,学会爬树...")
}
func (this *LittleMonkey) Swimming() {
	fmt.Println(this.Name, "通过学习,学会游泳...")
}

func main() {
	// 创建一个LittleMonkey实例/变量
	littleMonkey := LittleMonkey{
		Monkey{
			Name : "悟空",
		},
	}
	littleMonkey.Climbing()
	littleMonkey.Flying()
	littleMonkey.Swimming()
}

对上面代码的总结:
1、当A结构体继承了B结构体,那么A就自动继承了B的所有字段和方法,并且可以直接使用
2、当A结构体需要扩展功能,同时又不希望去破坏继承关系,可以通过去实现某个接口即可。因为我们可以认为:实现接口是对继承机制的补充。

(1)接口和继承解决的问题不同:
继承的价值在于:解决代码的复用性和可维护性
接口的价值在于:设计,设计好各种规范(方法),让其他自定义类型去实现这些方法。

(2)接口比继承更加灵活
继承是满足is-a的关系,而接口只需满足like-a的关系。

(3)接口在一定程序上实现代码解耦

五、多态

变量/实例具有多种形态。在Go中,多态特征是通过接口实现的。

六、类型断言

Golang学习之---面向“对象”编程(接口与多态)下(六)_第18张图片

6.1 基本介绍

类型断言,由于接口是一般类型不知道具体类型,如果要转成具体类型,就需要使用类型断言。如果指向要转成的类型,即类型匹配,ok;否则报错panic。示例如下:
Golang学习之---面向“对象”编程(接口与多态)下(六)_第19张图片

6.2 进行断言时,带上检测机制,成功就ok,失败也不要报panic
Golang学习之---面向“对象”编程(接口与多态)下(六)_第20张图片

6.3 类型断言的最佳实践1
Golang学习之---面向“对象”编程(接口与多态)下(六)_第21张图片

6.4 类型断言的最佳实践2
Golang学习之---面向“对象”编程(接口与多态)下(六)_第22张图片

你可能感兴趣的:(Go)