メソッドは、構造体(の型)と結びつけられた関数だ。Go はオブジェクト指向プログラミング言語ではないけど、このメソッドや構造体の埋め込み(これについては後で書くつもり)によって、オブジェクト指向的なプログラミングができるようになっている。
例を挙げよう。
前のエントリでは平面上の点を表す Point 構造体と、2点間の距離を求める distance 関数を作った。ここでもう一つ、3次元空間の点を表す Point3d 構造体を作る。この2点間の距離を求める関数を考えたとき、distance という名前は使えない。すでに名前を使ってしまっているからだ。
ところが、これらをそれぞれの構造体のメソッドにすれば、両方とも distance という名前にできる。
メソッドの一般亭な定義は次の通り。
func (仮引数 *型) 関数名(仮引数, ...) {
処理
}
ここで、関数名の前のカッコの中にある仮引数をレシーバと言い、このメソッドはレシーバの型と結びつけられる。これで、Point と Point3d の両方の構造体に、同じ distance という名前のメソッドが定義できるわけだ。
実際に書いてみよう。
package main
import (
"fmt"
"math"
)
type Point struct {
x, y float64
}
type Point3d struct {
x, y, z float64
}
func newPoint(x, y float64) *Point {
p := new(Point)
p.x, p.y = x, y
return p
}
func newPoint3d(x, y, z float64) *Point3d {
p := new(Point3d)
p.x, p.y, p.z = x, y, z
return p
}
func (p *Point) distance(q *Point) float64 {
dx := p.x - q.x
dy := p.y - q.y
return math.Sqrt(dx * dx + dy * dy)
}
func (p *Point3d) distance(q *Point3d) float64 {
dx := p.x - q.x
dy := p.y - q.y
dz := p.z - q.z
return math.Sqrt(dx * dx + dy * dy + dz * dz)
}
func main() {
p1 := newPoint(0.0, 0.0)
p2 := newPoint(10.0, 10.0)
q1 := newPoint3d(0.0, 0.0, 0.0)
q2 := newPoint3d(10.0, 10.0, 10.0)
fmt.Println(p1.distance(p2))
fmt.Println(q1.distance(q2))
}
^o^ > go run method.go 14.142135623730951 17.320508075688775