【问题标题】:How to make an interface method return another interface?如何让一个接口方法返回另一个接口?
【发布时间】:2019-09-27 07:38:38
【问题描述】:

我有一个接口,其中一个方法返回另一个接口的一部分。这是一个简单的表示:

type Garage interface {
    AllCars() []Car
}

type Car interface {
    Name() string
}

我也为此做了一个实现:

type MyGarage struct{}

func (g MyGarage) AllCars() []MyCar {
    return make([]MyCar, 0)
}

type MyCar struct {
    name string
}

func (c MyCar) Name() string {
    return c.name
}

现在在我的测试中我做了一个函数:

func TestAllCars(t *testing.T) {
    var garage Garage
    garage = new(mygarage.MyGarage)
    cars := garage.AllCars()
    fmt.Println(cars)
}

Go 抱怨 MyGarage 没有实现 Garage 接口,我理解但没想到,因为 MyCar 确实实现了 Car,所以这对我来说应该不是问题。

cannot use new(mygarage.MyGarage) (type *mygarage.MyGarage) as type Garage in assignment:
    *mygarage.MyGarage does not implement Garage (wrong type for AllCars method)
        have AllCars() []mygarage.MyCar
        want AllCars() []Car

我在这里做错了什么?

在 cmets 之后编辑

我尝试将方法更改为只返回一辆汽车,以避免围绕接口切片的问题,但它仍然抱怨。只是为了我想了解发生了什么。由于MyCar 实现了Car 我没想到会出现以下错误:

*mygarage.MyGarage does not implement Garage (wrong type for GetCar method)
    have GetCar() mygarage.MyCar
    want GetCar() Car

我认为问题在于强类型返回类型,MyCar 不是 Car,但应该可以将其强制转换为一个,但 Go 不接受将其作为 Garage 接口的有效实现?

【问题讨论】:

  • MyGarage.AllCars()必须返回[]Car[]MyCar不一样。
  • 是的,但这会产生我试图避免的依赖关系。既然MyGarage 可以在没有依赖的情况下实现Garage,为什么MyCar 不能对Car 做同样的事情?
  • 这是因为一个接口切片不是一个接口见下面github.com/golang/go/wiki/InterfaceSlice
  • 请注意,函数/方法的签名是它的类型。 T 类型实现接口IT 类型必须实现I 的方法,并且方法的类型/签名必须匹配逐字

标签: go interface


【解决方案1】:

这与不是接口的接口切片有关,也就是说,我认为下面的内容可以满足您的需求。

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

type Garage interface {
    AllCars() []Car
}

type Car interface {
    Name() string
}

type MyGarage struct{

}

func (g MyGarage) AllCars() []Car {
    x := []Car{MyCar{}}
    return x
}

type MyCar struct {
    name string
}

func (c MyCar) Name() string {
    return c.name
}

func main() {
    var garage Garage
    garage = MyGarage{}
    cars := garage.AllCars()
    fmt.Println(cars)
}

【讨论】:

  • 是的,这与 icza 在 cmets 中给出的建议类似,但考虑到 Garage 和 MyGarage 位于不同的包中,这将创建从 package[MyGarage] 到 package[Garage] 的依赖关系(有权访问到接口 Car) 因为 MyGarage 实现 Garage 不需要这种依赖关系,所以我希望避免它。
  • 我猜你是对的,但上层代码肯定应该有接口,你的包应该实现那个接口,这是因为编排这个的代码需要比下层实现更多的知识,话虽如此,这更像是一个问题,即您的包界面设计和布局是否正确
  • 另外,我将回到我关于接口切片不是接口的评论,使用上面的代码,我们仍然不是在纯接口中谈论我们实际上是在谈论切片,在你的方法中返回包含接口作为元素的切片,因为我链接的文档有帮助,所以当你说它不接受实际上不是正在发生的抽象时,它不接受包含接口元素的静态切片类型,请阅读上面的文档,它解释了我的意思,然后我可以发表评论。
猜你喜欢
  • 2010-10-05
  • 1970-01-01
  • 1970-01-01
  • 2021-11-01
  • 2018-07-07
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 2011-05-24
相关资源
最近更新 更多