开发者学堂课程【Go 语言核心编程 - 面向对象、文件、单元测试、反射、TCP 编程:面向对象编程必要性】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/626/detail/9666
面向对象编程必要性
Go 语言的面向对象编程与传统的面向对象编程(如 Java、donite 等语言)有很大区别。此处,应在“面向对象”中的“对象”二字加引号,意思是 Go 语言的面向对象与传统意义的面向对象含义不同,前者没有“类”的概念,而是使用“结构体”来替代“类”的概念,即在面向对象中,结构体的地位类似于 class。因此,在学习 Go 语言中面向对象编程时,要注意其与传统意义上面向对象编程的异同点。
一、结构体的引入
通过“养猫猫的问题”理解为什么需要面向对象编程。
张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。另一只叫小花,今年100岁,花色。请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,则显示张老太没有这只猫猫。
1.使用现有技术解决
通过对解决该问题的现有技术/传统方法的缺点进行分析,进而理解结构体与其他数据类型的区别及结构体的优点。
(1)使用单独的定义变量解决,即用变量记录猫的各个信息
①思路分析:
一共有2只猫,且每只猫都对应姓名、年龄和颜色3个特征,因此,应定义6个变量。
②代码演示:
package main
import (
"fmt"
)
func main() {
var cat1Name string = "小白"
var cat1Age int = 3
var cat1color string = "白色"
var cat2Name string = "小花"
var cat2Age int = 100
var cat2Color string = "花色"
//这种单独定义变量的方式过于繁琐,定义的变量数可能很多,无法通过一个变量将猫对应的特征属性取出,无法继续编写。
fmt.Println("ok")
}
(2)使用数组解决,将猫的信息放在数组中来解决
对于每只猫,其各个特征对应的变量属性不同,如名字是 string 类型的变量,年龄是int类型的变量,颜色是 string类型的变量。
代码演示:
package main
import (
"fmt"
)
func main() {
var catNames [2]string = [...]string{"小白","小花"}
var catAges [2]int = [...]string(3,100)
var catColors [2]string = [...]string("白色","花色")
// 由于猫的“名称”“年龄”“花色”分别属于不同的数组,若输入猫的名称“小白”,要输出其年龄、花色等信息较为困难,代码无法继续编写。
fmt.Println("ok")
}
如上两段代码,若不输入 fmt.Println("ok"),则会显示代码中的
包“fmt”未使用;且由于定义的变量/数组未使用,代码在运行时会报错。
综上,无论是通过变量或者数组的方式解决该问题都较为困难,原因在于:这两种方法将数据分散记录,不利于进行数据管理和维护,每只猫的属性不止一个,且这些属性都同时属于一个对象,故而使用这两种方法对各个属性分散记录不利于进行数据管理和维护;这两种方法无法对现有数据进行操作,如假设题目中猫的属性中还包括一些行为,如“猫通过训练可以做算术题”等,这两种方法无法体现。
(3)使用 map 解决
该种方法同样存在数据类型不一致的问题,通过 map[string]string 可以保存名字的信息,却无法同时保存年龄信息,因为两者对应的变量数据类型不同;此外,也存在各数据需分散记录的问题,
2.现有技术的缺点分析
(1)使用变量或数据来解决“养猫”问题时,均不利于数据的管理与维护。因为猫的名字、年龄、颜色的信息均属于一只猫,但是具体操作时,却将这些信息分开进行了保存。
(2)若要对每只猫的属性(名字、年龄、颜色)进行操作(绑定方法)也很难处理。
使用传统方法来处理这种一个对象具有多个属性的情形十分困难,因此,我们不使用传统的方法进行编程,而可以使用结构体的方法来解决。结构体是什么?结构体有何特征?即是我们本章节要学习的内容。