问题描述
我想在我的库中提供一个可以'扩展'的方法的基础结构。
I want to provide a base struct with methods in my library that can be 'extended'.
这个基础结构的方法依赖于扩展结构中的方法。
这在Go中是不可能的,因为struct方法只能访问结构自己的字段,而不能访问父结构。
The methods of this base struct rely on methods from the extending struct.This is not directly possible in Go, because struct methods only have acces to the structs own fields, not to parent structs.
重点是具有我不必在每个扩展类中重复的功能。
我已经提出了这种模式,它工作正常,
但由于它的周期性结构,看起来很复杂。
I have come up with this pattern, which works fine,but looks quite convoluted due to it's cyclical structure.
我从来没有在其他Go代码中找到类似的东西。
这是不是很好吗?
我可以采取哪种不同的方法?
I have never found anything like it in other Go code.Is this very un-go?What different approach could I take?
type MyInterface interface {
SomeMethod(string)
OtherMethod(string)
}
type Base struct{
B MyInterface
}
func (b *Base) SomeMethod(x string) {
b.B.OtherMethod(x)
}
type Extender struct {
Base
}
func (b *Extender) OtherMethod(x string) {
// Do something...
}
func NewExtender() *Extender {
e := Extender{}
e.Base.B = &e
return &e
}
推荐答案
正如人们的评论中所提到的,Go鼓励构成而不是继承。
As mentioned in people's comments, Go encourages composition over inheritance.
要解决有关减少代码重复的问题,你想使用。
To address your question about reducing code duplication, you would want to use embedding.
使用,你从非常狭窄的界面开始,只做几件事:
Using the example from Effective Go linked above, you start with very narrow interfaces that only do a few things:
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
然后你可以将接口组合在一起到另一个接口:
Then you can either compose interfaces together into another interface:
// ReadWriter is the interface that combines the Reader and Writer interfaces.
type ReadWriter interface {
Reader
Writer
}
它对于结构体的工作方式类似,你可以在另一个结构中组合实现Reader和Writer的结构:
It works similarly for structs, where you can compose structs that implement Reader and Writer together in another struct:
type MyReader struct {}
func (r *MyReader) Read(p []byte) (n int, err error) {
// Implements Reader interface.
}
type MyWriter struct {}
func (w *MyWriter) Write(p []byte) (n int, err error) {
// Implements Writer interface.
}
// MyReadWriter stores pointers to a MyReader and a MyWriter.
// It implements ReadWriter.
type MyReadWriter struct {
*MyReader
*MyWriter
}
基本上,任何实现 Reader
或 Writer
的东西都可以通过在struct中组合它们来重用,外部结构将自动实现 ReaderWriter
接口。
Basically, anything that implements a Reader
or a Writer
can be reused by composing them together in a struct, and that outer struct will automatically implement ReaderWriter
interface.
这基本上是在做,它对测试也非常有用。
This is basically doing Dependency Injection, and it's super useful for testing too.
示例来自上面的结构代码:
Example from the struct code above:
func (rw *MyReadWriter) DoCrazyStuff() {
data := []byte{}
// Do stuff...
rw.Read(data)
rw.Write(data)
// You get the idea...
}
func main() {
rw := &MyReadWriter{&MyReader{}, &MyWriter{}}
rw.DoCrazyStuff()
}
有一点需要指出,与oth略有不同语言的组合范例是 MyReadWriter
结构现在既可以作为 Reader
又可以作为作家
。这就是为什么在 DoCrazyStuff()
我们做 rw.Read(data)
而不是 rw。 Reader.Read(data)
。
One thing to point out that's slightly different from other languages' composition paradigm is that the MyReadWriter
struct can now act as both a Reader
and a Writer
. That's why in DoCrazyStuff()
we do rw.Read(data)
instead of rw.Reader.Read(data)
.
UPDATE:修正了不正确的例子。
UPDATE: Fixed incorrect example.
这篇关于Golang和继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!