是否可以从 Golang 中的父结构调用重写方法? [英] is it possible to call overridden method from parent struct in Golang?

查看:30
本文介绍了是否可以从 Golang 中的父结构调用重写方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to implement such code, where B inherit from A and only override A's Foo() method, and I hope the code to print B.Foo(), but it still print A.Foo(), it seems that the receiver in Golang can't work like this in C++, in which when dynamic binding is enabled, the code can work like what I want.

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

I also post another piece of code, which works, but it's too hard to implement, and more like a hack way, I think it's not a Golang style.

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

So my problem is: if the parent's Bar() method has some logic, for example, open a file, then read some lines, and use Foo() to output these lines to stdout, and the Child (in the example is B) wants to use most of them, the only difference is that the Child wants Foo() to output the lines to another file. How should I implement it? I have heard that Golang's inheritance can't work like C++ or Java, and what's right way in 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()

推荐答案

正如你所写的,Go 所拥有的并不是真正的继承,允许像特性一样继承的方法叫做 Embedding.

As you wrote, what Go has is not really inheritance, the method that allows inheritance like features is called Embedding.

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

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

What it means basically is that the embedded struct has no idea that it is embedded, so you cannot override anything that is called from it. You can actually take the embedded struct and take a reference for it only from the embedding struct.

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

So your best way to do it is more or less like your second example - through some sort of dependency injection using interfaces. i.e - A has a reference to some interface that does the actual work, say worker, that writes to a file or whatever. Then when instantiating B, you also replace A's worker with another worker (you can do it even without embedding A of course). The A just does something like myWorker.Work() without caring what worker it is.

这篇关于是否可以从 Golang 中的父结构调用重写方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆