Композиция, объединяющая данные и функции с интерфейсами и структурами
Мне интересно, если это что-то, что сделано в Go или я думаю об этом все неправильно: сочинять type x interface
а также type x struct
поэтому мои методы интерфейса также имеют доступ к определенным данным:
Программист C по моему хочет сделать это:
type PluginHandler interface {
onLoad()
pm *PluginManager
}
func (ph PluginHandler) onLoad() {
pm.DoSomething()
}
Там у меня есть интерфейс, определенный с функцией, но также некоторые данные, которые я хочу передать этим функциям, но это синтаксическая ошибка.
Так это что-то выполнимое в Go через какой-то другой метод, или я просто думаю о проблеме неправильно?
3 ответа
Вы определили onLoad
неправильно. Вы не можете определить функцию непосредственно по типу интерфейса.
Если у вас есть интерфейс, вам нужен другой тип для реализации методов, указанных в интерфейсе. Например, если другой тип реализует onLoad
метод, они автоматически (неявно) реализуют интерфейс PluginHandler
,
Другая вещь, которую вам нужно сделать, это изменить тип функции интерфейса, чтобы принять необходимые данные:
type PluginHandler interface {
onLoad(*PluginManager)
}
struct SomeType {
// ...
}
func (s SomeType) onLoad(pm *PluginManager) { // SomeType now implements
pm.DoSomething() // PluginHandler interface.
}
Таким образом, вы можете вводить в зависимости от того, что PluginManager
требуется PluginHandler
,
Также вы можете использовать SomeType
как PluginHandler
Тип, где требуется.
func someFuntion(ph PluginHandler) {
// ...
ph.onLoad(pm)
// ...
}
Может вызываться с входным аргументом типа SomeType
:
s := SomeType{}
someFunction(s)
TL;DR; Прямого перевода на Go нет.
Длинный ответ:
Go интерфейсы - это всего лишь методы.
Структуры Го являются только данными (с возможностью приемных методов).
Вы можете ссылаться и даже вставлять интерфейсы в структуры:
type Frobnicator interface {
Frobnicate() error
}
type Widget struct {
Frobnicator
WidgetName string
}
Но это не совсем то, о чем ты говоришь.
Я считаю, что лучший ответ на вашу дилемму - сделать шаг назад. Вы сосредотачиваетесь на деревьях, и вам нужно смотреть на лес. Go использует другой подход, чем C или классические ОО-языки, такие как C++ и Java.
Посмотрите на общую проблему, которую нужно решить, и найдите решение этой проблемы в Go. Это может быть болезненным процессом (я могу сказать из опыта), но это действительно единственный способ выучить новый способ мышления.
Просто для записи, вы можете добавить дополнительные методы к существующему типу, введя другой (косвенный) тип как:
type HandlerManager PluginManager
func (x *HandlerManager) onLoad() {
((*PluginManager)(x)).DoSomething()
}
И если вам нужно более общее решение, комбинация шаблонов адаптера и стратегии может помочь:
type PluginHandlerAdapter struct{ _onLoad func() }
func (x *PluginHandlerAdapter) onLoad() {
x._onLoad()
}
Используется как (открытый / закрытый доступ игнорируется):
type PluginManager struct {
PluginHandlerAdapter
}
func NewPluginManager() *PluginManager {
res := new(PluginManager)
res._onLoad = res.DoSomething
return res
}