我想实现这样的代码,其中B继承A,只覆盖A的Foo()方法,希望代码打印B.Foo(),但还是打印A.Foo(),看来接收器在Golang 在 C++ 中不能这样工作,其中启用动态绑定时,代码可以像我想要的那样工作。
我也贴了另外一段代码,可以用,但是太难实现了,更像是hack的方式,我觉得不是Golang的风格。
所以我的问题是:如果父的 Bar() 方法有一些逻辑,比如打开一个文件,然后读取一些行,并使用 Foo() 将这些行输出到stdout,而 Child(在示例中为 B)想要要使用其中的大部分,唯一的区别是 Child 希望 Foo() 将行输出到另一个文件。我应该如何实施它?听说Golang的继承不能像C++或Java那样工作,请问Golang的正确方法是什么?
stdout
package main import ( "fmt" ) type A struct { } func (a *A) Foo() { fmt.Println("A.Foo()") } func (a *A) Bar() { a.Foo() } type B struct { A } func (b *B) Foo() { fmt.Println("B.Foo()") } func main() { b := B{A: A{}} b.Bar() } output: A.Foo()
以下作品有效,但在写入时
a := A{} a.Bar()
你会遇到编译器错误
package main import ( "fmt" ) type I interface { Foo() } type A struct { i I } func (a *A) Foo() { fmt.Println("A.Foo()") } func (a *A) Bar() { a.i.Foo() } type B struct { A } func (b *B) Foo() { fmt.Println("B.Foo()") } func main() { b := B{A: A{}} b.i = &b // here i works like an attribute of b b.Bar() output: B.Foo()
正如你所写的,Go 所拥有的并不是真正的继承,这种允许类似特性的继承的方法称为 Embedding。
http://golang.org/doc/effective_go.html#embedding
这基本上意味着嵌入的结构不知道它是嵌入的,所以你不能覆盖从它调用的任何东西。您实际上可以采用嵌入结构并仅从嵌入结构中获取对它的引用。
所以你最好的方法或多或少像你的第二个例子 - 通过使用接口的某种依赖注入。ie - A 引用了一些执行实际工作的接口,例如worker写入文件或其他任何内容。然后在实例化 B 时,您还可以将 A 替换worker为另一个工人(当然,即使不嵌入 A,您也可以这样做)。A 只是做一些类似的事情,myWorker.Work()而不关心它是什么工人。
worker
myWorker.Work()