【问题标题】:How to implement two different interfaces with the same method signature如何使用相同的方法签名实现两个不同的接口
【发布时间】:2015-03-23 08:21:49
【问题描述】:

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

我在包里有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 !
}

如何处理这种情况?

【问题讨论】:

  • 没有什么可处理的:Any 类型有一个方法Do() string 实现both 接口A.DoerB.Doer
  • 我认为你是对的@Volker,没有解决办法,这种情况可能发生在任何使用接口的语言中(例如java)。

标签: interface go


【解决方案1】:

作为FAQ mentions

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

在你的情况下,你会满足这两个接口。

您可以通过以下方式测试一个(接口类型的)对象是否满足另一个接口类型A.Doer

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

OP 补充说:

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

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

  • 一个DoerA,它将您的对象C 作为一个字段,并以满足A.Do() 应该如何工作的方式实现A.Do()
  • 一个DoerB,它具有与您相同的对象C 作为字段,并以满足B.Do() 应该如何工作的方式实现B.Do()

这样,您将知道将哪个 Doer 传递给期望 A.DoerB.Doer 的函数。
您不必在原始对象C 上实现Do() 方法,这将无法处理A.Do()B.Do() 的不同逻辑。

【讨论】:

  • 但是Do方法中实现的满足A 的逻辑与B中的逻辑完全不同。
  • 谢谢@VonC,我也是,我添加了更多代码来澄清这个问题。
【解决方案2】:

根据定义,you are satisfying both:

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

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

a) 将 cmets 添加到定义您对逻辑的期望的接口方法(参见 io.Reader 接口或一个很好的示例)

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

【讨论】:

    猜你喜欢
    • 2011-12-13
    • 1970-01-01
    • 2015-03-11
    • 2022-01-22
    • 1970-01-01
    • 2011-07-26
    • 2015-11-02
    • 2017-12-19
    • 1970-01-01
    相关资源
    最近更新 更多