【发布时间】:2016-07-19 22:19:59
【问题描述】:
我无法找到解决代码重复问题的“捷径”。这就是问题所在。考虑以下几点:
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 添加更多方法时,我必须添加大量样板代码……特别是对于SharedFunctionality 和 N 种类型,我必须像上面的 4 一样拼出 M*N 单行。
我会喜欢做的事情是这样的:
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
这看起来可行,但仍然感觉样板代码太多。
还有其他选择吗?
【问题讨论】:
-
您已经大致概述了您的选择。并在下面查看戴夫的答案。想一想:如果一个具体类型除了
key()之外已经有一个MethodA()方法,会发生什么?至少 嵌入 使得MethodA()的含义明确(在“最浅深度”)。 -
您的问题本质上是“我如何在 go 中执行实现继承和虚拟方法”,但我认为您可能遇到了 xy 问题。 meta.stackexchange.com/questions/66377/what-is-the-xy-problem 。如果你描述一下你正在做的事情的背景,可能有一个不植根于 java 风格的面向对象设计的解决方案更适合 go。
标签: go interface refactoring code-duplication