如你所知,封装、继承、多态和抽象是面向对象编程的4个基本特征,本文描述Golang语言是如何实现这些特征的。
1 Golang的面向对象类型
Golang实现面向对象的两个关键类型是struct和interface,其中struct类似C++的普通类类型,interface则对应抽象类类型。与C++采用public/protected/private指示成员和方法的可见性不同,Golang采用大小写标识可见性,即大写字母开头的成员/方法对外可见,小写开头的则属于类的私有成员,外部不可以直接访问。此外,Golang与C++在类类型的定义上还有一个重要区别,那就是Golang在struct内只需要声明类的成员变量,而不需要在类定义体内声明或定义所有的方法,方法定义都在struct之外完成。好了,我们开始正文。
2 Golang的面向对象实现
2.1 封装
学生有姓名、年龄和专业等属性,于是我们定义一个Student类型如下:
type Student struct {
name string
age int
major string
}
学生可以跟大家打招呼:
func (s Student) SayHi() {
fmt.Printf("Hi, I am %s aged %d, and my major is %s\n", s.name, s.age, s.major)
}
在函数定义的func关键字后面加上我们定义的Student类型变量定义,这个函数就成为了Student的方法。类图表示如下:
值得注意的是,在Golang内,除slice、map、channel和显示的指针类型属于引用类型外,其它类型都属于值类型,前者作为函数入参传递时,函数对参数的修改会影响调用对象,而后者作为入参时,函数体内会生成调用对象的拷贝,函数对入参的修改不会影响调用对象。因此,如果我们要给Student类定义一个“构造函数”,我们希望的是这个函数的入参可以被赋值到Student的成员内,则该“构造函数”应该使用指针类型对象定义:
func (s *Student) Init(name string, age int, major string) {
s.name = name
s.age = age
s.major = major
}
我们来测试一下:
s := Student{
}
s.Init("pirlo", 21, "cs")
s.