为什么在直接实现的接口上的此类型声明失败?

时间:2018-10-10 12:12:21

标签: go methods interface composition type-assertion

我正在努力使用Go的Type Assertion机制。在下面的示例中,Qux.(Bar)的类型声明失败。

为什么在DoBar()处直接实现Qux不能完全填充Bar接口?

软件包主要

import (
    "fmt"
)

type Nameable interface {
    Name() string
}

type Foo interface {
    Nameable
    DoFoo() string
}

type Bar interface {
    Nameable
    DoBar() string
}

type bar struct {
    name string
}

func (b bar) Name() string {
    return b.name
}

// Qux embeds bar and is expected to fullfill Nameable interface
type Qux struct {
    bar
}

func (q *Qux) DoBar() string {
    return "DoBar"
}

func Check(subject Nameable) {
    if N, ok := subject.(Nameable); ok {
        fmt.Printf("%s has Nameable\n", N.Name())
    } 

    if F, ok := subject.(Foo); ok {
        fmt.Printf("%s has Foo: %s\n", F.Name(), F.DoFoo())
    }

    if B, ok := subject.(Bar); ok {
        fmt.Printf("%s has Bar: %s\n", B.Name(), B.DoBar())
    }
}

func main() {
    Check(bar{name: "bar"})
    Check(Qux{bar: bar{name: "Qux"}})
}

https://play.golang.org/p/PPkUMUu58JW

输出:

bar has Nameable
Qux has Nameable

1 个答案:

答案 0 :(得分:1)

Qux.DoBar()具有指针接收器,因此仅*Qux实现Bar而不实现Qux。类型Qux和指向其的指针类型*Qux是具有不同的method sets的不同类型。

使用类型*Qux的值会实现Bar

Check(&Qux{bar: bar{name: "*Qux"}})

这将输出(在Go Playground上尝试):

*Qux has Nameable
*Qux has Bar: DoBar

此外,如果您将Qux.DoBar()的接收者更改为非指针:

func (q Qux) DoBar() string {
    return "DoBar"
}

然后Qux*Qux都将实现Bar

Check(bar{name: "bar"})
Check(Qux{bar: bar{name: "Qux"}})
Check(&Qux{bar: bar{name: "*Qux"}})

输出(在Go Playground上尝试):

bar has Nameable
Qux has Nameable
Qux has Bar: DoBar
*Qux has Nameable
*Qux has Bar: DoBar

查看相关问题:X does not implement Y (... method has a pointer receiver)