【问题标题】:Does a struct implement all the interfaces that one of their embedded type implement?结构是否实现了其嵌入式类型之一实现的所有接口?
【发布时间】:2015-08-10 15:20:37
【问题描述】:

我有这个例子

// 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。在此示例中,添加 accept s(类型 B)作为输入。 B 实现 C

但是当我将 Incr() 方法从原始更改为

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

编译器报错

./main.go:35: 不能在参数中使用 s(类型 B)作为类型 C AddContent: B 没有实现 C(Incr 方法有指针接收器)

所以我仍然很困惑一个结构是否实现了它们的一种嵌入式类型实现的所有接口。

【问题讨论】:

    标签: struct go


    【解决方案1】:

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

    但是,当您将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)
    

    relevent portion of the spec

    给定一个结构类型 S 和一个名为 T 的类型,提升的方法是 包含在struct的方法集中如下:

    • 如果 S 包含匿名字段 T,则 S 和 *S 的方法集都包含带有接收者 T 的提升方法。*S 的方法集也 包括带有接收器 *T 的提升方法。
    • 如果 S 包含匿名字段 *T,则 S 和 *S 的方法集都包含带有接收者 T 或 *T 的提升方法。

    【讨论】:

      【解决方案2】:

      如果 S 包含匿名字段 T,则 S 和 *S 的方法集都包含带有接收者 T 的提升方法。*S 的方法集还包括带有接收者 *T 的提升方法。

      如果 S 包含匿名字段 *T,则 S 和 *S 的方法集都包括 带有接收器 T 或 *T 的提升方法。

      B 嵌入了 A,因此 B 的方法集包括带有接收器 A 的 protomoted 方法,但不包括 *A

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-07
        • 2010-09-08
        • 2010-11-10
        • 2010-09-21
        • 2020-11-22
        • 2015-08-19
        • 1970-01-01
        相关资源
        最近更新 更多