面向对象编程
面向对象编程将对象作为编程语言的核心,这意味着在构建和设计整个项目的时候,首先考虑的是行动的主体——对象,再去给对象附加应该具备的字段和行为。
封装、继承、多态是面向对象编程的三大特性。Go 语言也同样对这三大特性进行了支持。但是再 Go 语言中我们可以采用面向对象和面向过程的混合编程方式。
封装
封装是将属于某个对象的字段和行为抽象出来,形成一个有机体,可以使用权限机制来保护字段和方法,使其不能被其他的代码直接访问。
Go 语言中通过大小写来控制字段和方法的访问权限,大写字母开头的字段和方法是公开的,小写字母开头的字段和方法是私有的。
我们可以使用 struct
来定义一个对象:
type Worker struct {
Name string
Age int
Position string
}
成员函数可以通过 func
关键字定义:
func (w Worker) Work() {
fmt.Printf("%s is working\n", w.Name)
}
函数名前面的 w Worker
是接收者,表示函数 Work
是 Worker
类型的方法。调用方法的时候,可以通过 .
运算符来调用:
w := Worker{Name: "Alice", Age: 20, Position: "Engineer"}
w.Work()
要注意的是,上面我们定义的 Work
方法是值接收者,在这种情况下,Work
方法对 w
的修改不会影响到原始对象。
func (w Worker) Work() {
fmt.Printf("%s is working\n", w.Name)
w.Name = "Bob"
}
w.Work()
fmt.Println(w.Name) // Alice
运行结果:
Alice is working
Alice
可见,Work
方法对 w
的修改不会影响到原始对象。
如果我们想要修改原始对象,可以使用指针接收者:
func (w *Worker) Work() {
fmt.Printf("%s is working\n", w.Name)
w.Name = "Bob"
}
w.Work()
fmt.Println(w.Name) // Bob
运行结果:
Alice is working
Bob
继承
Go 语言不提供类似 extends 的关键字来实现继承,我们可以使用组合的方式来实现继承。
type Person struct {
Name string
Age int
}
func (p Person) Say() {
fmt.Printf("%s is saying\n", p.Name)
}
type Worker struct {
Person
Position string
}
func (w Worker) Work() {
fmt.Printf("%s is working\n", w.Name)
}
Worker
类型嵌套了 Person
类型,这样 Worker
就拥有了 Person
的字段和方法。
w := Worker{Person: Person{Name: "Alice", Age: 20}, Position: "Engineer"}
w.Say()
w.Work()
运行结果:
Alice is saying
Alice is working
将字段进行匿名化:
type Worker struct {
Person
Position string
}
声明时:
h := Person{Name: "Alice", Age: 20}
w := Worker{
h,
}