Golang和继承

the*_*uke 27 inheritance idiomatic go

我想在我的库中提供一个可以"扩展"的方法的基础结构.

此基础结构的方法依赖于扩展结构中的方法.这在Go中是不可能的,因为struct方法只能访问结构自己的字段,而不能访问父结构.

关键是要具有我不必在每个扩展类中重复的功能.

我已经提出了这种模式,它运行良好,但由于它的循环结构看起来很复杂.

我从来没有在其他Go代码中找到类似的东西.这是非常不合适的吗?我可以采取哪种不同的方法?

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
}
Run Code Online (Sandbox Code Playgroud)

Add*_*son 26

正如人们的评论中所提到的,Go鼓励构成而不是继承.

要解决有关减少代码重复的问题,您可能需要使用嵌入.

使用上面链接的Effective Go示例,您可以从非常狭窄的接口开始,只做几件事:

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以将接口组合到另一个接口:

// ReadWriter is the interface that combines the Reader and Writer interfaces.
type ReadWriter interface {
    Reader
    Writer
}
Run Code Online (Sandbox Code Playgroud)

它对于结构体的工作方式类似,您可以在另一个结构中组合实现Reader和Writer的结构:

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
}
Run Code Online (Sandbox Code Playgroud)

基本上,任何实现a Reader或a的东西Writer都可以通过在结构中组合它们来重用,而外部struct会自动实现ReadWriter接口.

这基本上是做依赖注入,它对测试也非常有用.

上面结构代码的示例:

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()
}
Run Code Online (Sandbox Code Playgroud)

有一点需要指出的是,与其他语言的组合范式略有不同的是,MyReadWriter结构现在可以同时充当a Reader和a Writer.这就是DoCrazyStuff()我们做的原因rw.Read(data)而不是rw.Reader.Read(data).

更新:修正了不正确的例子.

  • 除非您几乎从不想使用指向接口的指针。您的`MyReadWriter` 应该**不** 使用指向接口的指针,而是应该使用`type MyReadWriter struct { Reader, Writer }`。这允许(例如)`rw := MyReadWriter{ strings.NewReader("foo"), new(bytes.Buffer) }`。 (2认同)
  • 获取有关接口的更多详细信息的好地方是 [Russ Cox 的博客文章](http://research.swtch.com/interfaces)。 (2认同)

tux*_*21b 6

很抱歉让你失望,但你提出了错误的问题.当我开始编写Go代码时,我遇到了类似的问题.

您不能简单地采用类层次结构并将其转换为Go代码,至少不能获得令人满意的结果.通常在Go中有一种非常优雅和简单的方法来解决这些问题,但是为了发现它们,你需要像以前那样思考一下.

不幸的是,你的问题没有说任何东西什么问题,你正在试图解决的问题.您刚刚描述了如何解决它.因此,我有点不愿意给出一般答案,因为它不会导致惯用的Go代码.我理解你是否对这个答案感到失望,但在我看来,这是你能得到的最有价值的答案:)

  • 这是评论,而不是问题的答案。 (6认同)