1. 程式人生 > >Go語言的面向對象(OOP)

Go語言的面向對象(OOP)

nal 隱式 指針方法 println sam 類型 light 需要 sta

一、方法

在函數聲明時,在其名字之前放上一個變量,即是一個方法。這個附加的參數會將該函數附加到這種類型上,即相當於為這種類型定義了一個獨占的方法。如:

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
}

待續

Go語言的面向對象(OOP)