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

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


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

}

如何处理这种情况?


LEATH
浏览 239回答 2
2回答

慕妹3146593

正如常见问题中提到的使用其他语言的经验告诉我们,拥有多种名称相同但签名不同的方法有时很有用,但在实践中也可能会令人困惑和脆弱。仅按名称匹配并要求类型一致是 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 传递给期望 anA.Doer或 a的函数B.Doer。您不必Do()在原始 object 上实现一个方法C,这将无法处理A.Do()and的不同逻辑B.Do()。

一只甜甜圈

根据定义,您同时满足以下两点:Go 类型通过实现该接口的方法来满足该接口,仅此而已。此属性允许在无需修改现有代码的情况下定义和使用接口。它支持一种促进关注点分离和改进代码重用的结构类型,并使构建随着代码开发而出现的模式变得更加容易。接口的语义是 Go 具有敏捷、轻量级感觉的主要原因之一。因此,考虑到这一点,您可以:a) 向定义您对逻辑的期望的接口方法添加注释(请参阅 io.Reader 接口或一个很好的示例)b) 在接口上添加一个名为ImplementsDoerA 和ImplementsDoerB 的额外方法(也在FAQ 中提到)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go