类型组合:覆盖接口类型

Hen*_*yTK 3 struct overriding interface embedding go

我想组成另一种类型的类型,但用假的替换其中一个字段(这是一个接口值).我得到的问题是正在使用底层字段,所以我似乎无法覆盖该字段.

我在这里演示了这个问题:https://play.golang.org/p/lHGnyjzIS-Y

package main

import (
    "fmt"
)

type Printer interface {
    Print()
}

type PrinterService struct {}

func (ps PrinterService) Print() { fmt.Println("PrinterService") }

type Service struct {
    Client PrinterService
}

func (s Service) PrintViaMethod() { s.Client.Print() }

type FakeService struct {
    Service
    Client Printer
}

type SomeOtherService struct {}

func (sos SomeOtherService) Print() { fmt.Println("SomeOtherService") }

func main() {
    s := FakeService{Client: SomeOtherService{}}
    s.PrintViaMethod()
}
Run Code Online (Sandbox Code Playgroud)

为什么要打印"PrinterService"?我想要它打印"SomeOtherService".

谢谢.

icz*_*cza 5

通过s.PrintViaMethod(),你正在调用提升的方法FakeService.Service.PrintViaMethod(),方法接收器将FakeService.Service是类型Service,并Service.PrintViaMethod()调用Service.Client.Print(),其中Service.Client类型PrinterService,这就是它打印的原因"PrinterService".

在Go中有嵌入,但没有多态性.在结构中嵌入类型时,嵌入类型的方法会被提升,并且将成为嵌入器类型的方法集的一部分.但是当调用这种提升的方法时,它将获得嵌入值作为接收者,而不是嵌入者.

为了达到你想要的效果,你必须PrintViaMethod()通过为FakeService类型(带FakeService接收器类型)和内部调用提供它的实现来"覆盖"该方法FakeService.Client.Print().

通过这样做s.PrintViaMethod()将表示该FakeService.PrintViaMethod()方法将处于PrintViaMethod()存在(而不是FakeService.Service.PrintViaMethod())的最浅深度处.这在Spec:Selectors中有详细说明.

例如:

func (fs FakeService) PrintViaMethod() {
    fs.Client.Print()
}
Run Code Online (Sandbox Code Playgroud)

然后输出将是(在Go Playground上尝试):

SomeOtherService
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅相关问题和答案:

转换嵌入式struct call子方法代替父方法

Go中是否存在脆弱的基类问题?