OOP 在 go 中的应用感觉怪怪的,不过还好比较简单,而且跟传统的 OO 思想完全不同,感觉毁三观。
go 的方法非常有意思,在函数名前加个变量和类型,就是为该类型添加了方法。当然只能在自定义类型上声明方法。
type Point struct{ X, Y float64 }
// 为 Point 类型添加 Distance 方法。
func (p Point) Distance(q Point) float64 {
return math.Hypot(q.X-p.X, q.Y-p.Y)
}
// 调用方法
p := Point{1, 2}
q := Point{4, 6}
fmt.Println(p.Distance(q)) // "5", method call
方法的参数 (p Point)
里的 p 叫做方法的接收器(receiver),和传统 OO 不一样,不是 this
或 self
,这里的接收器仅仅是个变量,往往采用类型首字母命名。
在函数参数调用的时候,其实是复制了一份变量,方法也是一样,所以如果要修改该对象的数据,那么应该使用指针。
package main
import "fmt"
type Point struct{ X, Y int }
func (p Point) SetPoint1(x, y int) {
p.X = x
p.Y = y
}
func (p *Point) SetPoint2(x, y int) {
p.X = x
p.Y = y
}
func main() {
point1 := Point{11, 11}
point2 := Point{11, 11}
point1.SetPoint1(22, 22)
point2.SetPoint2(33, 33)
fmt.Printf("%v/n", point1) // {11 11}
fmt.Printf("%v/n", point2) // {33 33}
}
这个例子可以直接看到区别了,如果不用指针就无法修改对象的值。
其实应该 (&point2).SetPoint2
方式调用,但是编译器帮我们隐式调用了。
简单描述,就像是继承,只是方式有点怪怪的,跟结构体的嵌入是一样的。
方法可以当做值赋值给其他变量,方便调用,整理跟 js 有非常大的区别,因为不涉及 context 概念,js 必须通过 bind 来处理,而 go 不需要。
一个对象的变量或者方法如果对调用方是不可见的话,一般就被定义为“封装”。封装有时候也被叫做信息隐藏,同时也是面向对象编程最关键的一个方面。
本章概念不多,但感觉实际应用会踩很多坑,这需要在以后应用中慢慢掌握。光语法来说,还是非常容易掌握的。