当前位置: 首页 > 面试题库 >

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

唐渊
2023-03-14
问题内容

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

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

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


问题答案:

我会回答我自己的问题

首先,我只是在官方常见问题解答中找到了关于这些接口为何不被视为相似的答案: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


 类似资料:
  • 问题内容: 在以下代码中,我不明白为什么当它属于两个不同的对象时具有相同的ID? 问题答案: 我认为这是正在发生的事情: 取消引用时,将在内存中创建其副本。该存储位置由以下位置返回 由于没有引用到刚刚创建的方法的副本,因此GC将其回收,并且该内存地址再次可用 取消引用时,将在相同的内存地址(可用)中创建它的副本,您可以再次使用该地址。 第二个副本是GCd 如果您要运行一堆其他代码并再次检查实例方法

  • 我有以下场景: 以下是我的问题: 如果中的静态方法是公共的,则编译错误将为: 静态方法m1()与I中的抽象方法冲突。 因此,当访问修饰符是默认值时,它试图隐藏,而当它是公共的时,它是冲突的。为什么会有这样的区别呢?背后的理念是什么?

  • 只是延伸问题... 抽象类和接口中的相同方法 假设一个类实现了一个接口并扩展了一个抽象类,两者都有相同的方法(名称签名),但返回类型不同。现在,当我重写方法时,只有当我使返回类型与接口声明相同时,它才会编译。 另外,如果该方法在抽象类或接口中声明为private或final,会发生什么情况? **旁注。在一次采访中,爱因斯坦先生在这个问题上坚持了相当长的时间。有没有一个流行的场景,我们这样做,或者

  • 问题内容: 考虑以下示例: 失败并出现以下错误 为什么呢 生成的方法没有重叠。事实上,这实际上意味着 那里没有重叠。那为什么会失败呢? 如果您想知道我在做什么,并且有更好的解决方案:我有一堆Event和Listener接口,它们几乎与上述类完全一样。我想创建一个适配器和一个适配器接口,为此,我需要使用特定事件扩展所有Listener接口。这可能吗?有一个更好的方法吗? 问题答案: 不,你不能。这是

  • 问题内容: 我以为运算符检查对象的相等性。但事实并非如此: 问题答案: *Python *将相同的内存 位置用于方法和,这是*两个对象,它们的生命周期不重叠,因此对它们返回相同的标识。请参阅下面的详细说明。 从is运算符的文档中: 运算符是否测试对象标识:并且仅当x和y是同一对象时,x is y才是true。 从ID的文档中 返回对象的“身份”。这是一个整数(或长整数),在此对象的生存期内,此整数

  • 问题内容: 以下代码可以正常工作。在两个不同的结构上操作并打印该结构的字段的两种方法: 在控制台中显示所需的输出: 现在 ,如果我以以下方式更改方法签名,则会出现编译错误。我只是将方法的接收者移动到方法的参数: 我什至无法编译程序: 问 :为什么 当 方法具有相同的名称和Arity 时 ,我可以在接收器中互换结构类型,而不能在参数中互换结构类型? 问题答案: 因为Go不支持在其参数类型上重载用户定