LoginSignup
47
26

More than 3 years have passed since last update.

埋め込み型としての構造体 ( Goは継承を使わない )

Last updated at Posted at 2018-11-13
  • Goには継承という概念がない。そのため構造体をうまく利用して埋め込み作業をしていく。
  • Goでは構造体の中に構造体を埋め込むことで再利用性を高めたり、コード量を減らすことが出来る。
  • person型とcitizen型はどちらも独立しており、親子関係にはならない。(is-a関係)
main.go

package main

import "fmt"

type person struct {
    Name string
}

type citizen struct {
    Country string
    person
}

func (p person) greet() string {
    return fmt.Sprintf("Hello, %s", p.Name)
}

func main() {
    c := citizen{
        Country: "japan",
    }
    c.Name = "hoge" // c.person = &person{ Name: "hoge" } でも同じ

    // func(p Person)Greet()string が呼びだされる。
    // func(c Citizen)Greet()string を定義した場合はこっちが呼ばれる。
    greeting := c.greet()

    fmt.Println(greeting)
}

  • 上記の例を違う関数から間接的に呼び出そうとすると失敗する
main.go

package main

import "fmt"

type person struct {
    Name string
}

type citizen struct {
    Country string
    person
}

func (p person) greet() string {
    return fmt.Sprintf("Hello, %s", p.Name)
}

// この関数を追加
func speak(p person) string {
    return p.greet()
}

func main() {
    c := citizen{
        Country: "japan",
    }
    c.Name = "hoge"

    // これはエラーになる
    greeting := speak(c) 
    // => speak(c.person) これはうまくいく

    fmt.Println(greeting)
}

  • 埋め込まれている構造体でもそのまま呼び出せるようにするにはインターフェースを活用する
main.go

 package main

import "fmt"

type person struct {
    Name string
}

type citizen struct {
    Country string
    person
}

type greeter interface {
    greet() string
}

func (p person) greet() string {
    return fmt.Sprintf("Hello, %s", p.Name)
}

// interfaceを使って引数を定義する
func speak(g greeter) string {
    return g.greet()
}

func main() {
    c := citizen{
        Country: "japan",
    }
    c.Name = "hoge"

    p := person{
        Name: "fuga",
    }

    greeting1 := speak(c)
    greeting2 := speak(p)

    fmt.Println(greeting1) // Hello, hoge
    fmt.Println(greeting2) // Hello, fuga
}

  • 上記のようにすることでコードが見やすくなったり、共通化を行いやすくなる
  • interface自体は関数をまとめて一つのオブジェクトを作ることができる便利なものである

参照
Goはオブジェクト指向言語だろうか?
オブジェクト指向言語としてGolangをやろうとするとハマる点を整理してみる-Qiita
インタフェースの実装パターン #golang

47
26
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
47
26