面向对象编程(OOP)是软件开发中的重要理念,虽然Go语言的方式与传统的OOP有些不同,但它依然支持这些基本特性。本文将简要介绍Golang如何使用结构体实现面向对象的三大特性:封装、继承和多态。
1.结构体的定义
由于Golang中没有类的概念,因此Golang中的struct和其他语言中的class有着同等的地位,可以使用struct来实现面向对象的诸多特性。
type Student struct {
Name string
Age int
ID int
}
func main() {
// 先定义 后赋值
var s1 Student
s1.Name = "luoaoxuan"
s1.Age = 21
s1.ID = 1001
// 定义时赋值
s2 := Student{"tangjiaxian", 25, 1005}
// 使用new关键字创建对象指针
var s3 *Student = new(Student)
s3.Name = "luaox"
s3.Age = 18
s3.ID = 1006
// 按key赋值
s4 := Student{
Name: "tjx",
Age: 40,
ID: 1007,
}
fmt.Println(s1)
fmt.Println(s2)
fmt.Println(*s3)
fmt.Println(s4)
}
注意,GO语言中的结构体指针类型变量,在访问结构体中的成员变量时,可以直接使用点.不用使用箭头->.并且结构体是用户单独定义的类型,和其他类型进行转换时需要有完全相同的字段(名字,个数和类型).GO语言中的type相当于取别名,取的别名GO语言认为它是一种新的数据类型
2.方法的实现
在Golang中,方法和函数的不同在于书写方式的不同,方法需要与结构体进行绑定。
func speak1() {
fmt.Println("函数-学生说")
}
func (s Student) speak2() {
fmt.Println("方法-学生说")
}
func main() {
s2 := Student{"tangjiaxian", 25, 1005}
speak1() // 函数
s2.speak2() // 方法
}
上面的代码中,speak2就是结构体方法,第一个括号内容: (s Student),证明这个方法绑定的是结构体Student,只有结构体Student变量才能访问这个方法,并且这个代码中的方法是结构体对象的值传递,所以方法内修改是不会影响外面的变量的。
3.封装的实现
在Golang中,没有public,private,protected等关键字,一般是通过变量名的大小写来控制变量的访问范围,大写字母开头的属性是包外可用的,小写字母开头的属性是只有包内可用的。Golang包内声明的变量、结构体、类型、函数等都是一样的规则,大写字母开头则对外可见,反之对外不可见。
type Student struct {
Name string
Age int
ID int
sex string // 私有 只有包内能访问
}
func (s *Student) SetSex(sex string) {
s.sex = sex
}
func (s *Student) GetSex() string {
return s.sex
}
4.继承的实现
在Golang中,如果一个struct嵌套了另外一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现了继承特性。
type People struct {
Name string
}
type Student struct {
StudentId int
People //复用父类,加入匿名结构体
}
func main() {
s := Student{}
s.StudentId = 1001
s.Name = "luoaoxuan"
// 等价于 s.People.Name = "luoaoxuan"
fmt.Println(s)
}
注意,这里变量s是Student类型,它访问父类People类中的变量或方法时,可以直接用.访问到,而不是使用s.People.Name 的方式,GO语言在这一块做了简化。并且不建议将父类和子类的变量重名。GO语言支持多继承,即一个结构体嵌套多个匿名结构体。
5.接口与多态
接口的存在是为了定义规则,规范或某种具体的功能,它需要使用interface关键字,使用结构体和接口可以实现多态特性。
type Cat struct {
Name string
}
type Dog struct {
Name string
}
type Animal interface {
speak() //声明一个没有实现的方法
}
//实现具体的方法
func (c Cat) speak() {
fmt.Println("喵~")
}
//实现具体的方法
func (d Dog) speak() {
fmt.Println("旺~")
}
func call(a Animal) {
a.speak()
}
func main() {
c := Cat{}
d := Dog{}
call(c)
call(d)
}
上例实现了动物的接口,动物都会叫,只要实现了叫的方法,我们就认为其是动物,因此猫是动物,狗也是动物,因为它们都会叫。即实现了多态。
注意,在Golang中,interface{}代表空接口,任何类型都可以看作空接口,空接口是所有类的父类。





