英文:
Composition combining data and functions with interfaces and structs
问题
我想知道这是否是Go语言中的一种做法,或者我是否完全错误地思考了这个问题:通过组合type x interface
和type x struct
,使得我的接口方法也可以访问特定的数据:
我想要像C语言程序员那样做:
type PluginHandler interface {
onLoad()
pm *PluginManager
}
func (ph PluginHandler) onLoad() {
pm.DoSomething()
}
在这里,我定义了一个带有函数的接口,但是还有一些数据我想要传递给这些函数,但是这是一个语法错误。
所以,是否有其他方法可以在Go语言中实现这个功能,还是我对问题的思考方式有误?
英文:
I'm wondering if this is something that's done in Go or if I'm thinking about it all wrong: composing type x interface
and type x struct
so my interface methods have access to specific data too:
The C programmer in my wants to do this:
type PluginHandler interface {
onLoad()
pm *PluginManager
}
func (ph PluginHandler) onLoad() {
pm.DoSomething()
}
There I have an interface defined with a function, but also some data I want to pass to those functions but this is a syntax error.
So is this something that's doable in Go through some other method or am I just thinking about the problem wrong?
答案1
得分: 2
你已经错误地定义了onLoad
。你不能直接在接口类型上定义一个函数。
一旦你有了一个接口,你需要另一个类型来实现接口中指定的方法。例如,如果另一个类型实现了onLoad
方法,它们就会自动(隐式地)实现PluginHandler
接口。
另一件需要做的事情是将接口函数类型更改为接受所需数据:
type PluginHandler interface {
onLoad(*PluginManager)
}
type SomeType struct {
// ...
}
func (s SomeType) onLoad(pm *PluginManager) { // SomeType现在实现了
pm.DoSomething() // PluginHandler接口。
}
这样,你可以注入任何PluginHandler
所需的PluginManager
。
此外,你可以在需要的地方将SomeType
用作PluginHandler
类型。
func someFunction(ph PluginHandler) {
// ...
ph.onLoad(pm)
// ...
}
可以使用SomeType
作为输入参数的类型调用:
s := SomeType{}
someFunction(s)
英文:
You have defined onLoad
incorrectly. You cannot define a function directly on interface type.
Once you have an interface, you need another type to implement methods specified in the interface. For example, if another type implements onLoad
method, they automatically (implicitly) implement the interface PluginHandler
.
The other thing you need to do is change the interface function type to accept the required data:
type PluginHandler interface {
onLoad(*PluginManager)
}
struct SomeType {
// ...
}
func (s SomeType) onLoad(pm *PluginManager) { // SomeType now implements
pm.DoSomething() // PluginHandler interface.
}
This way, you get to inject whichever PluginManager
required by PluginHandler
.
Also, you can use SomeType
as a PluginHandler
type whereever required.
func someFuntion(ph PluginHandler) {
// ...
ph.onLoad(pm)
// ...
}
Can be called with an input argument of type SomeType
:
s := SomeType{}
someFunction(s)
答案2
得分: 1
TL;DR; Go没有直接的翻译。
长答案:
Go的接口只包含方法。
Go的结构体只包含数据(可以有接收者方法的可能性)。
你可以在结构体中引用甚至嵌入接口:
type Frobnicator interface {
Frobnicate() error
}
type Widget struct {
Frobnicator
WidgetName string
}
但这并不是你所说的。
对于你的困境,我认为最好的答案是:退一步。你现在过于关注细节,需要放眼整体。Go采用了与C、C++和Java等传统面向对象语言不同的方法。
看看要解决的一般问题,并在Go中找到解决方案。这可能是一个痛苦的过程(我可以从经验中说),但这确实是学习新思维方式的唯一途径。
英文:
TL;DR; There is no direct translation to Go.
Long answer:
Go interfaces are only methods.
Go structs are only data (with the possibility of receiver methods).
You can reference, and even embed interfaces within structs:
type Frobnicator interface {
Frobnicate() error
}
type Widget struct {
Frobnicator
WidgetName string
}
But that's not really what you're talking about.
The best answer to your dilema is, I believe: Take a step back. You're focusing on the trees, and you need to look at the forest. Go takes a different approach than C, or classical OO languages like C++ and Java.
Look at the general problem to be solved, and find solutions to that in Go. This can be a painful process (I can say from experience), but it's really the only way to learn the new way of thinking.
答案3
得分: 0
只是为了记录,你可以通过引入另一个(间接)类型来向现有类型添加额外的方法,例如:
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
}
英文:
Just for the record, you can add extra methods to an existing type, by introducing another (indirection) type as:
type HandlerManager PluginManager
func (x *HandlerManager) onLoad() {
((*PluginManager)(x)).DoSomething()
}
And if you need to go with a more generic solution, a combination of Adapter & Strategy patterns could do:
type PluginHandlerAdapter struct{ _onLoad func() }
func (x *PluginHandlerAdapter) onLoad() {
x._onLoad()
}
Used like (public/private access ignored):
type PluginManager struct {
PluginHandlerAdapter
}
func NewPluginManager() *PluginManager {
res := new(PluginManager)
res._onLoad = res.DoSomething
return res
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论