一尘不染

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

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
}

并包装 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 !
}

如何处理这种情况?


阅读 233

收藏
2020-07-02

共1个答案

一尘不染

正如常见问题解答所提到的

其他语言的经验告诉我们,使用具有相同名称但签名不同的多种方法有时会很有用,但在实践中也可能会造成混淆和脆弱。
在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()应该如何工作的方式实现

这样,您将知道将哪个Doer传递给期望an A.Doer或a 的函数B.Doer
您将不必Do()在原始对象上实现一个方法C,该方法将无法应对A.Do()and 的不同逻辑B.Do()

2020-07-02