はじめに
最近Golangをはじめまして、Struct, Method, Interfaceをまとめてみました。
※ 間違い等ございましたら、ご指摘お願い致します。
Struct(構造体)
構造体とは?
Go言語にはオブジェクト指向におけるClass
という物が存在しません。
しかし、それと似たような役割を果たしてくれる変数が構造体です。
定義方法
struct
という型を使って定義します。
type Human struct {
name string
age int
}
初期化方法
初期化方法はいくつかの方法があります。
-
{}
を使い、順序にしたがって初期化する。
P := Human{"Sam",22}
-
field:value
の方法で初期化する。順序は任意。
P := Human{age:25, name:"Tom"}
-
new
関数を使い、変数定義後に初期化する。
P := new(Human)
それでは、一通り宣言してみます。
type Human struct {
name string
age int
}
func main() {
// 1. {}を使い、順序にしたがって初期化する。
sum := Human{"Sum", 22}
// 2. field:valueの方法で初期化する。順序は任意。
tom := Human{age: 25, name: "Tom"}
// 3. new関数を使い、変数定義後に初期化する。
bob := new(Human)
bob.name, bob.age = "Bob", 28
fmt.Printf("Name = %s Age = %d\n", sum.name, sum.age)
fmt.Printf("Name = %s Age = %d\n", tom.name, tom.age)
fmt.Printf("Name = %s Age = %d\n", bob.name, bob.age)
}
匿名フィールド
フィールドを継承して、新たなフィールドを宣言する方法です。
上記のHuman
を継承してStudent
を作成します。
type Human struct {
name string
age int
}
type Student struct {
Human // 匿名フィールド
speciality string
}
func main() {
sum := Student{Human{"Sum", 22}, "Computer Science"}
fmt.Printf("Name = %s Age = %d Speciality = %s\n", sum.name, sum.age, sum.speciality)
}
アクセスする際も、あたかも自分のフィールドのようにアクセスできます。
Method(メソッド)
メソッドとは?
任意の型に関連付けられた関数をメソッドと呼ぶ。
文法
func (r ReceiverType) funcName(parameters) results {
// 処理
}
定義方法
とりあえず書いてみます。
まずは、Circle
の構造体を作り、area()
メソッドで面積を返します。
type Circle struct {
radius float32 // 半径
}
func (c Circle) area() float32 {
return c.radius * c.radius * math.Pi
}
func main() {
c := Circle{5}
fmt.Printf("半径%.0fcmの円の面積=%.3fc㎡", c.radius, c.area())
}
匿名フィールドを使いメソッドを定義する
匿名フィールドを含むsturct
もメソッドを定義することができる。
type Human struct {
name string
age int
}
type Student struct {
Human
school string
}
type Employee struct {
Human
company string
}
func (s Student) SayHi() {
fmt.Println("私は学生です。")
}
func (e Employee) SayHi() {
fmt.Println("私は会社員です。")
}
func main() {
tom := Student{Human{"Tom", 18}, "hoge"}
sum := Employee{Human{"Sum", 30}, "fuga"}
tom.SayHi()
sum.SayHi()
}
同じ関数名で宣言しても名前空間が違うからエラーにはなりません。
Interface(インタフェース)
インタフェースとは?
簡単に言うと、「メソッドの組み合わせ」です。
メソッドの型だけを定義した型の一種であり、任意の型がどのようなメソッドを実装するべきかを規定するためのもの。
文法
type TypeName interface {
MethodName(parameters) results
}
定義方法
// 車の構造体
type Car struct {
speed int
}
// スポーツカーの構造体
type Sports struct {
Car
player string
}
// 走るためのインタフェース
type Runner interface {
Place()
Run()
}
func (c Car) Place() {
fmt.Print("道路を")
}
func (c Car) Run() {
fmt.Printf("%dキロで安全運転に走る。\n", c.speed)
}
func (s Sports) Place() {
fmt.Print("コースを")
}
func (s Sports) Run() {
fmt.Printf("%dキロで早く走る。\n", s.speed)
}
// インターフェスを引数に取る関数
func Run(r Runner) {
r.Place()
r.Run()
}
func main() {
c := Car{40}
s := Sports{Car{150}, "Tom"}
// インタフェースのRunner型の変数を用意
var r Runner
r = c
Run(r)
r = s
Run(r)
}
道路を40キロで安全運転に走る。
コースを150キロで早く走る。
インタフェースを使った関数
引数にインタフェースを取ることで、インタフェースを使いまわすこともできる。
// インターフェスを引数に取る関数
func Run(r Runner) {
r.Place()
r.Run()
}
使い方
func main() {
c := Car{40}
s := Sports{Car{150}, "Tom"}
// インタフェースのRunner型の変数を用意
var r Runner
r = c
Run(r)
r = s
Run(r)
}
1. 構造体の定義
最初は構造体を定義しているだけです。
c := Car{40}
s := Sports{Car{150}, "Tom"}
2. インタフェースの型の定義(ポイント)
r
はRunner
型の変数です!
var r Runner
3. 構造体の実体をインターフェース型の変数に代入
この時点でCar
型からRunner
型に変換されたと認識してよい。
r = c
4. インタフェースを使った関数(Run
)にr
を渡す
Run(r)
これと同様にスポーツカーにもします。
そうすると普通の車とスポーツカーとの場合で結果が変わります。
インタフェースを使うと、プログラムの柔軟性を与えることができますね。