У меня возникли проблемы с поиском «пути» для решения проблемы дублирования кода. Вот проблема. Рассмотрим следующий пример:Уменьшение дублирования кода в Golang
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
Похоже, что это может сработать, но оно все еще похоже на слишком много шаблонов.
Любые другие альтернативы?
Вы в значительной степени описали свои варианты. И см. Ответ Дэйва ниже. И подумайте об этом: что произойдет, если конкретный тип уже будет иметь метод MethodA(), кроме 'key()'? По крайней мере, _embedding_ делает однозначным то, что означало бы 'MethodA()' (на «самой мелкой глубине» _). – icza
Ваш вопрос по существу «как я наследую реализацию реализации и виртуальные методы в go», но я думаю, что, возможно, у вас есть проблема xy. http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem. Если вы описываете небольшой контекст того, что вы делаете, возможно, это решение, которое не связано с объектно-ориентированным дизайном в стиле Java, который лучше подходит для работы. –