Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Interface 如何使用相同的方法签名实现两个不同的接口_Interface_Go - Fatal编程技术网

Interface 如何使用相同的方法签名实现两个不同的接口

Interface 如何使用相同的方法签名实现两个不同的接口,interface,go,Interface,Go,假设我必须实现在两个不同包中声明的两个不同接口(在两个不同的独立项目中) 我的包裹里有A package A type interface Doer { Do() string } func FuncA(Doer doer) { // Do some logic here using doer.Do() result // The Doer interface that doer should implement, // is the A.Doer

假设我必须实现在两个不同包中声明的两个不同接口(在两个不同的独立项目中)

我的包裹里有
A

package A

type interface Doer {
    Do() string
}

func FuncA(Doer doer) {
     // Do some logic here using doer.Do() result

     // The Doer interface that doer should implement, 
     // is the A.Doer
}
和包装中的
B

package B

type interface Doer {
    Do() string
}

function FuncB(Doer doer) {
    // some logic using doer.Do() result

     // The Doer interface that doer should implement, 
     // is the B.Doer
}
在我的
main
软件包中

package main

import (
    "path/to/A"
    "path/to/B"
)

type C int

// this method implement both A.Doer and B.Doer but
// the implementation of Do here is the one required by A !
func (c C) Do() string {
    return "C now Imppement both A and B"
}

func main() {
    c := C(0)
    A.FuncA(c)
    B.FuncB(c) // the logic implemented by C.Do method will causes a bug here !
}
如何处理这种情况?

作为

使用其他语言的经验告诉我们,使用各种名称相同但签名不同的方法有时是有用的,但在实践中也可能令人困惑和脆弱。
在Go的类型系统中,仅按名称匹配并要求类型一致性是一个主要的简化决策

在您的情况下,您将满足这两个接口

您可以通过执行以下操作来测试(接口类型的)对象是否满足另一个接口类型
A.Doer

if _, ok := obj.(A.Doer); ok {
}

OP补充道:

但是
Do
方法中实现的满足
A
的逻辑与
B
中的逻辑完全不同

然后,您需要在对象周围实现一个包装器:

  • a
    DoerA
    ,它将对象
    C
    作为字段,并以满足
    a.Do()
    工作方式的方式实现
    a.Do()
  • a
    DoerB
    ,它具有与字段相同的对象
    C
    ,并以满足
    B.Do()
    工作方式的方式实现
    B.Do()
这样,您就可以知道将哪个执行者传递给一个函数,该函数需要
a.Doer
B.Doer

您不必在原始对象
C
上实现
Do()
方法,这将无法处理
a.Do()
B.Do()
的不同逻辑

根据定义,

Go类型通过实现接口的方法来满足接口,仅此而已。此属性允许定义和使用接口,而无需修改现有代码。它支持一种结构化类型,这种类型可以促进关注点的分离并改进代码的重用,并且更容易基于代码开发时出现的模式进行构建。界面的语义是Go灵活、轻量级感觉的主要原因之一

因此,考虑到这一点,您可以:

a) 在接口方法中添加注释,定义您对逻辑的期望(请参阅io.Reader接口或一个好的示例)


b) 在接口上添加一个名为ImplementsDoerA和ImplementsDoerB的额外方法(也在常见问题解答中提到)。

完全没有什么需要处理的:任何类型都有一个方法
Do()字符串
实现两个接口
a.Doer
b.Doer
。我认为你是对的@Volker,没有解决办法,这种情况可能发生在任何使用接口的语言中(
java
),但是
Do
方法中实现的满足
A
的逻辑与
B
中的逻辑完全不同。谢谢@VonC,我也是,我添加了更多的代码来澄清这个问题。