小编典典

接口具有相同的方法,但被认为是不同的

go

为什么将两个使用相同方法的命名接口视为不同的接口,又如何避免呢?

假设我们有一个喜欢吃产品的人(食者)。他不在乎产品是什么,他只想指出从哪里可以买到新产品。换句话说,他想要产品服务,但并不关心产品服务将生产什么产品。在具体的实现中,我们将尝试用苹果喂他,因此我们将为他提供appleService。

结果如下:

./main.go:9: cannot use appleService (type *service.AppleService) as type eater.ProductServiceI in function argument:
        *service.AppleService does not implement eater.ProductServiceI (wrong type for New method)
                have New() service.ProductI
                want New() eater.ProductI

接口service.AppleIeater.AppleI具有相同的方法Eat(),除了golang之外,别无其他。为什么以及如何避免这种情况?根据鸭子的说法,这应该起作用,因为实际ProductServiceI需要的是提供的struct具有Eat()方法-
它不必关心名称具有接口(service.ProductIvs eater.ProductI)。

下面是完整的代码:

==> ./main.go <==

package main

import "./apple/service"
import "./eater"

func main() {
    appleService := &service.AppleService{}
    // func eater.New(productService ProductServiceI)
    appleEater := eater.New(appleService) 
    appleEater.EatUntilHappy()
}

==> ./eater/eater.go <==

package eater

type ProductServiceI interface {
    New() ProductI
}

type ProductI interface {
    Eat()
}

type Eater struct {
    productService ProductServiceI
}

func New(productService ProductServiceI) *Eater {
    return &Eater{
        productService: productService,
    }
}

func (a *Eater) EatUntilHappy() {
    for i:=0; i < 5; i++ {
        product := a.productService.New()
        product.Eat()
    }
}

==> ./apple/service/service.go <==

package service

import "./apple"

type ProductI interface {
    Eat()
}

type AppleService struct {
}

func (a *AppleService) New() ProductI {
    return &apple.Apple{}
}

==> ./apple/service/apple/apple.go <==

package apple

import "fmt"

type Apple struct {
}

func (a *Apple) Eat() {
    fmt.Println("mniam, mniam")
}

我认为,只要声明相同,什么名称或导入路径都有接口都没有关系。


阅读 262

收藏
2020-07-02

共1个答案

小编典典

我会回答我自己的问题

首先,我只是在官方常见问题解答中找到了关于这些接口为何不被视为相似的答案:http
:
//golang.org/doc/faq#t_and_equal_interface

其次,在我的情况下,我可以使用匿名接口interface { Eat() }代替声明type ProductI interface { Eat() }

但是,如果出现来自go faq的示例 ,则不可能 。考虑一下:

type Equaler interface {
    Equal(Equaler) bool
}

type T int
func (t T) Equal(u Equaler) bool { return t == u.(T) }

如果您在这里使用相同的技巧,您将获得

type T int
func (t T) Equal(u interface{ Equal(interface{ Equal(...) bool }) bool }) bool { return t == u.(T) }

换句话说,您最终会遇到递归

以下是我使用此技巧的更新代码-它有效-有人可能会发现此技巧很有用。

==> ./eater/eater.go <==

package eater

type ProductServiceI interface {
    New() interface { Eat() }
}

type Eater struct {
    productService ProductServiceI
}

func New(productService ProductServiceI) *Eater {
    return &Eater{
        productService: productService,
    }
}

func (a *Eater) EatUntilHappy() {
    for i:=0; i < 5; i++ {
        product := a.productService.New()
        product.Eat()
    }
}

==> ./main.go <==

package main

import "./apple/service"
import "./eater"

func main() {
    appleService := &service.AppleService{}
    appleEater := eater.New(appleService)
    appleEater.EatUntilHappy()
}

==> ./apple/service/service.go <==

package service

import "./apple"

type AppleService struct {
}

func (a *AppleService) New() interface{ Eat() } {
    return &apple.Apple{}
}

==> ./apple/service/apple/apple.go <==

package apple

import "fmt"

type Apple struct {
}

func (a *Apple) Eat() {
    fmt.Println("mniam, mniam")
}

结果:)

# go run main.go
mniam, mniam
mniam, mniam
mniam, mniam
mniam, mniam
mniam, mniam
2020-07-02