LoginSignup
44
18

More than 3 years have passed since last update.

【Golang】 Struct, Method, Interfaceをまとめてみた

Posted at

はじめに

最近Golangをはじめまして、Struct, Method, Interfaceをまとめてみました。
※ 間違い等ございましたら、ご指摘お願い致します。

Struct(構造体)

構造体とは?

Go言語にはオブジェクト指向におけるClassという物が存在しません。
しかし、それと似たような役割を果たしてくれる変数が構造体です。

定義方法

structという型を使って定義します。

type Human struct {
    name string
    age  int
}

初期化方法

初期化方法はいくつかの方法があります。

  1. {}を使い、順序にしたがって初期化する。
    P := Human{"Sam",22}
  2. field:valueの方法で初期化する。順序は任意。
    P := Human{age:25, name:"Tom"}
  3. 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. インタフェースの型の定義(ポイント)
rRunner型の変数です!

var r Runner

3. 構造体の実体をインターフェース型の変数に代入
この時点でCar型からRunner型に変換されたと認識してよい。

r = c

4. インタフェースを使った関数(Run)にrを渡す

Run(r)

これと同様にスポーツカーにもします。
そうすると普通の車とスポーツカーとの場合で結果が変わります。

インタフェースを使うと、プログラムの柔軟性を与えることができますね。

44
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
44
18