Go语言的面向对象(OOP)
一、方法
在函数声明时,在其名字之前放上一个变量,即是一个方法。这个附加的参数会将该函数附加到这种类型上,即相当于为这种类型定义了一个独占的方法。如:
package geometry import "math" type Point struct{ X, Y float64 } // traditional function func Distance(p, q Point) float64 { return math.Hypot(q.X-p.X, q.Y-p.Y) } // same thing, but as a method of the Point type 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(Distance(p, q)) // "5", function call fmt.Println(p.Distance(q)) // "5", method call
上方代码里附加的参数p,叫做方法的接收器(receiver)。Go语言中不像其它语言使用this或self作为接收器,我们可以任意选择接收器的名字。为保持其在方法间传递时的一致性和简短性,建议使用其类型的第一字母。
当接收器变量本身比较大时(拷贝消耗资源较多),我们可以用其指针而不是对象来声明方法。如:
func (p *Point) ScaleBy(factor float64) { p.X *= factor p.Y *= factor } p := Point{1, 2} (&p).ScaleBy(2) fmt.Println(p) // "{2, 4}"
如果接收器p是一个Point类型的变量,并且其方法需要一个Point指针作为接收器,我们可以简写为p.ScaleBy(2)。编译器会隐式的帮我们用&p去调用ScaleBy这个方法。
这种简写只适用于"变量",不能通过一个无法取得地址的接收器来调用指针方法,如:Point{1,2}.scaleBy(2)。
GO语言中没有类似C++的Class关键字,以及直接的对象继承。不过可以通过嵌入结构体来扩展类型,在类型中内嵌的匿名字段也可以是一个命名类型的指针。如下:
type ColoredPoint struct { *Point color.RGBA }
待续