Skip to Content

入門Goプログラミング Lesson22(クラスがない)から学んだこと

Goにはクラスがない

クラス、オブジェクト、継承のような機能がない
オブジェクト指向設計から得たアイデアを応用するのに必要なものを提供している!

  • 構造化されたデータに振る舞いを提供するメソッドを書く
  • オブジェクト指向設計の原理を応用する

型と、型に対するメソッド、構造体の組み合わせにより、他の言語ではクラスが提供する機能の多くが手に入る

クラスに代わるもの

構造体とわずかなメソッドでほとんど同じ目的を達成できる

要点を整理するためにworld型を作成し、惑星の半径を表すフィールドを持たせる
その値を2点間の距離を計算するのに使う
distanceメソッドは地球のための数式の応用で火星の半径を使用している
distanceworld型に対するメソッドとして宣言することで、地球など火星以外の世界での距離も計算できるようになる

memo
このやり方のどこが優れているのか?
様々な半径を持つworld型で距離を計算できる、すっきりとした方法を提供する
世界の半径をdistanceメソッドに渡す必要がない
なぜなら、メソッド自身が世界の半径(w.radius)にアクセスできるから

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package main

import (
	"fmt"
	"math"
)

type location struct {
	lat, long float64
}
type world struct {
	radius float64
}

func main() {
	// Mars を数多く存在し得る世界の1つとして宣言
	var mars = world{radius: 3389.5}

	sprit := location{-14.5684, 175.472636}
	opportunity := location{-1.9462, 354.4734}

	// mars の distance メソッドを使う
	dist := mars.distance(sprit, opportunity)
	fmt.Printf("%.2f km\n", dist)
}

func (w world) distance(p1, p2 location) float64 {
	// 計算式について深く考える必要はない、こういうもの
	s1, c1 := math.Sincos(rad(p1.lat))
	s2, c2 := math.Sincos(rad(p2.lat))
	clong := math.Cos(rad(p1.long - p2.long))
	// world の radius フィールドを使う
	return w.radius * math.Acos(s1*s2+c1*c2*clong)
}

// rad 度数をラジアンに変換する
func rad(deg float64) float64 {
	return deg * math.Pi / 180
}
9669.71 km

まとめ

  • メソッドと構造体の組み合わせで、古典的な言語が提供する機能の多くを提供できる
  • コンストラクタ関数は普通の関数である

感想

急に難しくなった
オブジェクト指向が分かってないから理解が追いつかない