封装
Go语言中并没有特定的方式去定义一个所谓的“类”,所以,Go语言中实现对象中封装的方式比较特殊,通过在函数名字前(func和函数名之间)放上一个变量,从而实现将这个函数与该变量进行绑定,使这个函数成为该变量的一个独占方法,进而实现了封装这个特性
为了更贴合“类”这个概念,我们一般使用一个结构体来作为这个变量,下面给出一个例子
package main
import "fmt"
type Student struct {
ID int
Name string
}
func (stu Student) GetName() string {
return stu.Name
}
func main() {
stu := Student{ID: 1, Name: "Wei Yi"}
fmt.Println(stu.GetName())
}
我们可以将Student看作是一个类,stu是该类的一个对象,这个类有两个成员变量ID和Name,GetName的该类的一个方法,用于访问对象中的Name变量
Go语言相对于其他面向对象语言的一个特点是没有乱七八糟的private,protect,public等等(逃
有一点需要特别关注,这个函数名之前的变量可以理解为是这个函数的一个参数,所以这里存在两种写法
//类比值传递和地址传递
func (stu Student) GetName() string {
return stu.Name
}
func (stu *Student) GetName() string {
return stu.Name
}
后者其实是将这个方法绑定在这个变量的指针上,当我们需要修改这个对象里面的一个成员的时候,必须要用到后者的写法,不然修改的成员变量只是一个内存中的一个副本,原对象并没有发生改变
//正确的写法
func (stu *Student) SetName(name string) {
stu.Name = name
}
继承
Go语言中父类对子类的继承是通过结构体的嵌套实现的,把父类的类名放在子类的定义里,即可完成对父类的继承
不过多用语言解释,直接上代码
package main
import "fmt"
//父类
type Animal struct {
name string
}
//子类
type Cat struct {
Animal
}
//定义父类的方法
func (animal *Animal) Sleep() {
fmt.Println(animal.name + "is sleeping.")
}
func (animal *Animal) Walk() {
fmt.Println(animal.name + "is Walking.")
}
//定义子类的新方法
func (cat *Cat) Cry() {
fmt.Println(cat.name + ": MiaoMiao(new method)")
}
//重写父类的方法
func (cat *Cat) Sleep() {
fmt.Println("cat is sleeping(rewrite method).")
}
func main() {
var animal Animal
var cat Cat
animal.name = "小动物"
cat.name = "小猫"
animal.Walk()
cat.Walk() //继承父类的方法
animal.Sleep()
cat.Sleep() //重写过后的方法
cat.Cry()
}
运行结果
多态
Go语言中使用接口interface类型来实现多态。Go语言中的多态和Java里面的不同点是,它去除了所谓的继承关系。如果一个类实现了一个接口里的全部方法,即可认为这个类实现了这个接口,而并不需要将接口类型嵌套在这个类的结构体里。所以从本质上讲,Go语言里的接口实际上是一种指针。
package main
import "fmt"
type Animal interface {
Cry()
}
type Cat struct {
name string
}
type Dog struct {
name string
}
func (cat *Cat) Cry() {
fmt.Println("MiaoMiao")
}
func (dog *Dog) Cry() {
fmt.Println("WangWang")
}
func test(animal Animal) {
animal.Cry()
}
func main() {
var animal Animal
var dog Dog
var cat Cat
animal = &dog
animal.Cry()
animal = &cat
animal.Cry()
test(&dog)
test(&cat)
}
运行结果