💬

#golang defined typeの元の型のメソッドを呼び出す

2022/08/17に公開

1. struct embedded

defined typeではなくstruct embeddedを使う場合、シンプルに実現できる

1-1. ok

Int()メソッドの生えたID型を埋め込んだUserID型では、問題なく Int()を呼び出すことができる

type ID struct {
	uint64
}

func (id ID) Int() uint64{
	return id.uint64
}

type UserID struct {
	ID
}

func main() {
	userID := UserID{ID{1}}
	userID.Int() // 1
}

1-2. ok

ID型がstructではなくdefined typeによる定義でも問題ない

type ID uint64

func (id ID) Int() uint64{
	return uint64(id)
}

type UserID struct {
	ID
}

func main() {
	userID := UserID(ID(1))
	userID.Int() // 1
}

2. defined type

defined typeを用いる場合、ちょっと癖のある挙動をする

2-1. error

defined typeで定義されたID型を元にdefined typeされたUserID型からは、Int()を呼び出すことはできない

type ID uint64

func (id ID) Int() uint64{
	return uint64(id)
}

type UserID ID

func main() {
	userID := UserID(1)
	userID.Int() // userID.Int undefined
}

2-2. error

ID型がstructで定義されていたとしても、同様に呼び出すことはできない

type ID struct {
	uint64
}

func (id ID) Int() uint64{
	return id.uint64
}

type UserID ID

func main() {
	userID := UserID{1}
	userID.Int() // userID.Int undefined
}

2-3. ok

Int()メソッドの生えたidType型を埋め込んだID型を元にdefined typeされたUserID型ではInt()を呼び出すことができる

type idType uint64

func (id idType) Int() uint64{
	return uint64(id)
}

type ID struct {
	idType
}

type UserID ID

func main() {
	userID := UserID{1}
	userID.Int() // 1
}

2-4. ok

idType型がstructであっても同様に呼び出すことができる

type idType struct {
	uint64
}

func (id idType) Int() uint64{
	return id.uint64
}

type ID struct {
	idType
}

type UserID ID

func main() {
	userID := UserID{idType{1}}
	userID.Int() // 1
}

結論

defined typeのメソッドの継承は、structの要素のメソッドのみ継承される
元の型やstruct自体に生えているメソッドは継承されない

追記

Underlying Typeを考えると理解できる

それぞれのUnderlying Typeは以下のようになる

  • 2-1: uint64
  • 2-2: struct{ uint64 }
  • 2-3: struct{ idType }
  • 2-4: struct{ idType }

2-3, 2-4はidTypeのstruct embeddedとなるので、メソッド継承される

参照

Discussion