如何用相同的方法签名实现两个不同的接口 [英] How to implement two different interfaces with the same method signature

查看:214
本文介绍了如何用相同的方法签名实现两个不同的接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我在包 A

 包A 

类型接口Doer {
do()字符串
}

func FuncA(Doer doer){
//使用doer.Do()执行一些逻辑结果

// Doer应该实现的Doer接口,
//是A.Doer
}

并且在包中 B

 包B 

类型接口Doer {
Do()字符串
}

函数FuncB(Doer doer){
//使用doer.Do的某些逻辑()result

// doer应该实现的Doer接口,
//是B.Doer
}

在我的主要包中

  package main 

import(
path / to / A
path / to / B


类型C int

//这个方法实现A.Doer和B.Doer,但是
//这里执行Do是所需的一个 !
func(c C)Do()string {
returnC now imppement both A and B
}

func main(){
c := C(0)
A.FuncA(c)
B.FuncB(c)//由C.Do方法实现的逻辑会导致一个错误!
}

如何处理这种情况?

解决方案

正如常见问题解答


其他语言的使用经验告诉我们,使用名称相同但签名不同的多种方法偶尔有用,但也可能会造成混淆并且在实践中很脆弱。

仅通过名称进行匹配并要求类型一致性是Go类型系统中的一个主要简化决策


在您的情况下,您可以同时满足这两个界面。

您可以你可以通过这样做来测试一个对象(接口类型)是否满足另一个接口类型 A.Doer

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








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


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


  • a DoerA ,它的对象是 C 作为一个字段,并且以一种方式实现 A.Do()满足如何 A.Do()应该工作

  • a DoerB ,它的同一个对象 C 作为一个字段,并且以满足如下的方式实现 B.Do() B.Do()应该工作



这样,知道哪个Doer传递给函数,期望 A.Doer 或者 B.Doer

您不必在原始对象 C 上实现 Do()方法, ld无法应付 A.Do() B.Do()的不同逻辑。

Suppose that I have to implement two different interfaces declared in two different packages (in two different separated projects).

I have in the package 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
}

And in package 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
}

In my main package

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 !
}

How to deal with this situation ?

解决方案

As the FAQ mentions

Experience with other languages told us that having a variety of methods with the same name but different signatures was occasionally useful but that it could also be confusing and fragile in practice.
Matching only by name and requiring consistency in the types was a major simplifying decision in Go's type system.

In your case, you would satisfy both interfaces.

You can you the can test whether an object (of an interface type) satisfies another interface type A.Doer, by doing:

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


The OP adds:

But the logic implemented in the Do method to satisfy A is completely different from the one in B.

Then you need to implement a wrapper around you object:

  • a DoerA, which has your object C as a field, and implement A.Do() in a manner that satisfy how A.Do()is supposed to work
  • a DoerB, which has your same object C as a field, and implement B.Do() in a manner that satisfy how B.Do() is supposed to work

That way, you will know which Doer to pass to a function expecting an A.Doer or a B.Doer.
You won't have to implement a Do() method on your original object C, which would be unable to cope with the different logic of A.Do() and B.Do().

这篇关于如何用相同的方法签名实现两个不同的接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆