一个结构体是否实现了其嵌入类型实现的所有接口?

huangapple go评论80阅读模式
英文:

Does a struct implement all the interfaces that one of their embedded type implement?

问题

我有这个例子

// embed project main.go
package main

import (
	"fmt"
)

type A struct {
	A1 int
	A2 int
}

func (a A) Incr() int {
	a.A1++
	return a.A1
}

type B struct {
	A
	D int
}

type C interface {
	Incr() int
}

func Add(c C) {
	d := c.Incr()
	fmt.Println(d)
}

func main() {
	var s B
	s.Incr() //B has Incr
	Add(s)
}

使用这个例子,我想检查B是否实现了接口C。在这个例子中,Add函数接受s(类型为B)作为输入。B实现了C

但是当我将Incr()方法从原来的形式改为

func (a *A) Incr() int {
    a.A1++
    return a.A1
}

编译器会报错

> ./main.go:35: cannot use s (type B) as type C in argument to
> AddContent: B does not implement C (Incr method has pointer receiver)

所以我仍然困惑于一个结构体是否实现了其嵌入类型实现的所有接口。

英文:

I have this example

// embed project main.go
package main

import (
	"fmt"
)

type A struct {
	A1 int
	A2 int
}

func (a A) Incr() int {
	a.A1++
	return a.A1
}

type B struct {
	A
	D int
}

type C interface {
	Incr() int
}

func Add(c C) {
	d := c.Incr()
	fmt.Println(d)
}

func main() {
	var s B
	s.Incr() //B has Incr
	Add(s)
}

Using this example i wanted to check whether B implement interface C or not. In this example Add accept s (type B) as input. B implement C.

But when i change Incr() method from original to

func (a *A) Incr() int {
    a.A1++
    return a.A1
}

It compiler gives the error

> ./main.go:35: cannot use s (type B) as type C in argument to
> AddContent: B does not implement C (Incr method has pointer receiver)

So i am still confused whether a struct implement all the interface that one of their embedded type implement.

答案1

得分: 2

如果S包含一个匿名字段T,那么S和S的方法集都包括接收者为T的提升方法。而S的方法集还包括接收者为*T的提升方法。

如果S包含一个匿名字段T,那么S和S的方法集都包括接收者为T或*T的提升方法。

B嵌入了A,所以B的方法集包括接收者为A的提升方法,但不包括接收者为*A的提升方法。

英文:

> If S contains an anonymous field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
>
> If S contains an anonymous field *T, the method sets of S and *S both include
promoted methods with receiver T or *T.

B embedded A, so method sets of B include protomoted methods with receiver A, but does not include *A

答案2

得分: 2

是的,您的结构体实现了嵌入类型的方法集。

然而,当您将Incr的签名更改为func (a *A) Incr() int时,您需要一个指针作为该方法的接收器。当A本身具有指针接收器时,它本身不实现Incr

s.Incr()调用有效的原因是s的值是可寻址的,并且Go会自动引用它进行方法调用。当您将s传递给Add时,您试图将其转换为C接口,该值将不再是可寻址的,并且Incr方法不在方法集中。

在这种情况下,您可以将嵌入类型更改为*A

type B struct {
	*A
	D int
}

在调用点处获取s的地址

Add(&s)

或者将s更改为指针(*B):

s := &B{}
Add(s)

规范的相关部分

给定一个结构体类型S和一个名为T的类型,推广方法包括在结构体的方法集中,如下所示:

  • 如果S包含一个匿名字段T,则S和*S的方法集都包括具有接收器T的推广方法。S的方法集还包括具有接收器T的推广方法。
  • 如果S包含一个匿名字段T,则S和S的方法集都包括具有接收器T或*T的推广方法。
英文:

Yes, your struct implements the method set of the embedded type.

However, when you change the signature of Incr to func (a *A) Incr() int, you need a pointer for the receiver of that method. A itself doesn't implement Incr when it has a pointer receiver.

The reason the s.Incr() call works, is that the s value is addressable, and Go automatically references it for the method call. When you pass s to Add, you're attempting to convert it to a C interface, the value would no longer be addressable, and the Incr method isn't in the method set.

In this case, you can either change the embedded type to *A,

type B struct {
	*A
	D int
}

take the address of s at the call site

Add(&s)

or make s a pointer (*B):

s := &B{}
Add(s)

The relevent portion of the spec

> Given a struct type S and a type named T, promoted methods are
> included in the method set of the struct as follows:
>
> - If S contains an anonymous field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also
> includes promoted methods with receiver *T.
> - If S contains an anonymous field *T, the method sets of S and *S both include promoted methods with receiver T or *T.

huangapple
  • 本文由 发表于 2015年8月10日 23:20:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/31923371.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定