一尘不染

是否可以从 Golang 中的父结构调用重写方法?

go

我想实现这样的代码,其中B继承A,只覆盖A的Foo()方法,希望代码打印B.Foo(),但还是打印A.Foo(),看来接收器在Golang 在 C++ 中不能这样工作,其中启用动态绑定时,代码可以像我想要的那样工作。

我也贴了另外一段代码,可以用,但是太难实现了,更像是hack的方式,我觉得不是Golang的风格。

所以我的问题是:如果父的 Bar() 方法有一些逻辑,比如打开一个文件,然后读取一些行,并使用 Foo() 将这些行输出到stdout,而 Child(在示例中为 B)想要要使用其中的大部分,唯一的区别是 Child 希望 Foo() 将行输出到另一个文件。我应该如何实施它?听说Golang的继承不能像C++或Java那样工作,请问Golang的正确方法是什么?

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()

阅读 130

收藏
2021-12-26

共1个答案

一尘不染

正如你所写的,Go 所拥有的并不是真正的继承,这种允许类似特性的继承的方法称为 Embedding。

http://golang.org/doc/effective_go.html#embedding

这基本上意味着嵌入的结构不知道它是嵌入的,所以你不能覆盖从它调用的任何东西。您实际上可以采用嵌入结构并仅从嵌入结构中获取对它的引用。

所以你最好的方法或多或少像你的第二个例子 - 通过使用接口的某种依赖注入。ie - A 引用了一些执行实际工作的接口,例如worker写入文件或其他任何内容。然后在实例化 B 时,您还可以将 A 替换worker为另一个工人(当然,即使不嵌入 A,您也可以这样做)。A 只是做一些类似的事情,myWorker.Work()而不关心它是什么工人。

2021-12-26