LoginSignup
0
0

【Go言語】埋め込んだ構造体のフィールドやメソッドを同階層にあるとして扱える話

Posted at

構造体の埋め込みについて

例えば人を定義するとき、その構造体の中に「住所」という情報を混ぜることになったとします。このとき、以下のように構造体の中で構造体を利用することになります。これを構造体の埋め込みと言います。

package main

import "fmt"

type Address struct {
	Street     string
	City       string
	PostalCode int
}

type Person struct {
	FirstName string
	LastName  string
	Age       int
	Address
}

フィールドへのアクセス

このとき、Addressの中のStreetフィールドの値を利用するときは以下のようにアクセスすると思います。

func main() {
	p := Person{
		FirstName: "John",
		LastName:  "Doe",
		Age:       30,
		Address: Address{
			Street:     "123 Main St",
			City:       "Anytown",
			PostalCode: 12345,
		},
	}

	fmt.Println(p.Address.Street)
}

しかし、Go言語ではこのようにPerson構造体を宣言すると、インスタンス利用時には埋め込んだAddress構造体のフィールドがあたかも同階層で宣言されたかのようにアクセスすることが可能になります。

// 以下は同じ結果になる

fmt.Println(p.Address.Street)
// 123 Main St

fmt.Println(p.Street)
// 123 Main St

これはプロパティだけではなく、メソッドでも同じようにアクセスすることが可能になります。

Address構造体にGetAddress()をメソッドとして定義します。
この場合も同様に同階層にあるようにアクセスすることが可能になります。

func (a Address) GetAddress() string {
	return fmt.Sprintf("%s, %s, %d", a.Street, a.City, a.PostalCode)
}

func main() {
	p := Person{...

    // 以下2つは同じ結果
	fmt.Println(p.Address.GetAddress())
    fmt.Println(p.GetAddress())
}

複数の埋め込みと同名のフィールドがある場合

同名のフィールドがある場合は上記のようにアクセスすることはできなくなりエラーになります。
以下の場合コンパイルエラーになります。

type Address struct {
	Street     string
	City       string
	PostalCode int
}

type Person struct {
	FirstName string
	LastName  string
	Age       int
	Address
	ContactInfo
}

type ContactInfo struct {
	Email       string
	PhoneNumber string
	City        string
}

func main() {
	p := Person{...

	// Error : ambiguous selector p.City compiler(AmbiguousSelector)
	fmt.Println(p.City)
}

そのため上記のような場合はフィールド・メソッドともにどの構造体のフィールドにアクセスするのかを明示する必要が発生します

fmt.Println(p.Address.City)
fmt.Println(p.ContactInfo.City)

個人的には同階層として扱える状況でもどの構造体のフィールドにアクセスしているのか明示するほうが可読性が向上すると思いました

0
0
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
0
0