英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论