我无法找到" go-way"解决代码重复问题。这就是问题所在。请考虑以下事项:
type (
WithKey interface {
key() string
}
SharedFunctionality interface {
WithKey
MethodA() string
MethodB() string
// ... etc ...
}
FirstType struct { ... }
SecondType struct { ... }
// ... etc ...
)
func (ft *FirstType) key() string { ... }
func (st *SecondType) key() string { ... }
现在,SharedFunctionality
中的方法仅取决于key()
方法的结果。我可以像下面这样实现它们:
func runMethodA(k WithKey) string {
key := k.key()
// do something and return a string
}
func runMethodB(k WithKey) string {
key := k.key()
// do something else and return a string
}
func (ft *FirstType) MethodA() string { return runMethodA(ft) }
func (ft *FirstType) MethodB() string { return runMethodB(ft) }
func (st *SecondType) MethodA() string { return runMethodA(st) }
func (st *SecondType) MethodB() string { return runMethodB(st) }
我不喜欢这种方法是,当我添加更多类型(ThirdType,FourthType等)或者我向SharedFunctionality添加更多方法时,我必须添加大量的样板代码...特别是对于M方法SharedFunctionality和N种类型,我必须拼出M * N单行,如上面的4所示。
我爱要做的事情是:
func (k WithKey) MethodA() string {
key := k.key()
// do something
}
换句话说:我喜欢在接口类型上定义方法。含义:实现" WithKey"的所有对象会自动获取MethodA() string
,MethodB() string
等,因此会自动实现SharedFunctionality
界面。类似 Java接口中的默认方法。
但是,我知道在接口类型中定义方法是不可能的......
解决这个问题的方法是什么?
我已经看到了一种方法,我将使用接口类型的匿名字段创建一个结构,然后在那里实现这些方法:
type SharedFuncStruct struct {
WithKey
}
func (sfs *SharedFuncStruct) MethodA() string {
key := sfs.key()
// whatever
}
// same for MethodB()
然后使用它,我会做类似的事情:
first := ... getFirstTypeValue()
sfs := &SharedFuncStruct{first}
sfs.MethodA() // etc
看起来它可以工作,但它仍然感觉太多样板代码。
还有其他选择吗?
答案 0 :(得分:2)
在我看来,你需要提取一个包。我有这个功能的方式是
package keyed
type hasKey interface {
Key() string
}
func MethodA(k hasKey) string {
key := k.Key()
// whatever
}
func MethodB(k hasKey) string {
key := k.Key()
// whatever
}
然后
package your_package
import "keyed"
type (
FirstType struct { ... }
SecondType struct { ... }
)
func (ft *FirstType) Key() string { ... }
func (st *SecondType) Key() string { ... }
func main() {
first := &FirstType{}
second := &SecondType{}
keyed.MethodA(first)
keyed.MethodA(second)
keyed.MethodB(first)
keyed.MethodB(second)
}
答案 1 :(得分:1)
有趣的事实:您可以将接口嵌入到结构中,然后结构自动实现该接口。您可以使用它来有效地定义接口上的方法:
https://play.golang.org/p/ZufTOzr9ig
type (
WithKey interface {
key() string
}
SharedFunctionality interface {
WithKey
MethodA() string
MethodB() string
}
KeyHolder struct {
WithKey
}
FirstType struct { ... }
SecondType struct { ... }
)
func (k *KeyHolder) MethodA() string {
key := k.key()
// ...
}
func (k *KeyHolder) MethodB() string {
key := k.key()
// ...
}
func NewSharedFunctionality(w WithKey) SharedFunctionality {
return &KeyHolder{w}
}
func (ft *FirstType) key() string { ... }
func (st *SecondType) key() string { ... }
在这种情况下,KeyHolder
结构嵌入了WithKey
接口,因此可以容纳任何具有key() string
方法的内容(FirstType
和{{1}有)。然后,您可以在该结构上定义SecondType
和MethodA
,然后该结构将同时满足MethodB
接口(因为它嵌入它)和WithKey
接口,使用任何密钥由嵌入式SharedFunctionality
返回。
换句话说,不是将WithKey
包裹在FirstType
中,而是放在WithKey
中(意味着SharedFunctionality
本身必须定义FirstType
,{{1}在key()
中包装MethodA()
,然后将其(作为MethodB()
接口)嵌入到仅用于定义这些默认方法的其他结构中{} {1}}和FirstType
,然后履行WithKey
界面。