面向对象编程(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{}代表空接口,任何类型都可以看作空接口,空接口是所有类的父类。