面向对象编程
- 封装:通过方法实现
- 继承:通过匿名字段实现
- 多态:通过接口实现
匿名字段组合
type Person struct {
id int
}
type Student struct {
Person //结构体匿名字段,只有结构名。默认包含了Person字段的所有成员
name string
}
初始化
//顺序初始化
var student1 Student = Student{Person{1}, "H"}
//自动推导类型
student2 := Student{Person{1}, "H"}
//指定成员初始化
student3 := Student{Person: Person{id: 1}}
成员操作
student1.id = 2 //直接通过匿名字段中的成员变量名来调用
student1.name = "Z"
//也可以整体赋值
student1.Person = {3}
方法继承
//这里增加一段Person结构的方法
func (p Person) PrintInfo() {
fmt.Printf("id = %d \n", p.id)
}
//main中声明的Student是可以调用Person中的方法的
func main() {
student := Student{Person{1}, "a"}
student.PrintInfo()
}
方法重写
- 子类写了同名方法
- 当方法重写后首先调用子类方法(就近原则)
- 也可以显式调用父类方法。例如:
student.Person.PrintInfo()
方法
绑定特殊字段的函数;
和特殊类型关联的函数;
- go语言中可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法
- 方法总是绑定对象实例,并隐式将实例作为第一实参,方法的语法如下:
func (receiver ReceiverType) funcName(parameters) (results)
- 参数receiver可以任意命名,若方法中未曾使用,可以省略参数名
- ReceiverType可以是普通类型也可以是指针类型。但基类型不能是接口或指针
- 不支持方法重载
//修改自己的变量在函数中修改会影响到函数外
func (student Student) ChangeName(newName string) {
student.name = newName
}
调用
//通过:(接收返回参数 =) 变量名.方法名(传入参数) 来调用
student1.ChangeName("H")
值语义和引用语义
- 接收者为指针变量时为引用语义
- 接收者为普通变量时为值语义
指针变量和普通的方法集
当结构体变量是一个指针变量时,它能够调用的方法称为方法集
声明的变量都可以同时调用值语义和引用语义的方法
方法值
方法变量名 := 变量名.方法
- 隐藏了接收者
- 使用一个变量名来保存方法调用。例如:
sFunc := student.PrintInfo
sFunc(传入参数)
方法表达式
方法变量名 := 类型.方法
- 接收者用结构来表示
- 使用一个变量名来保存方法调用。例如:
sFunc := Person.PrintInfo
sFunc := (*Pserson).PrintInfo
sFunc(student.Person(需要设定哪个成员调用该方法), ...传入参数)
sFunc((&student).Person(需要设定哪个成员调用该方法), ...传入参数)