一尘不染

类型组成:覆盖接口类型

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

为什么打印"PrinterService"?我要打印"SomeOtherService"

谢谢。


阅读 233

收藏
2020-07-02

共1个答案

一尘不染

通过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())的最浅深度。规格:选择器中对此进行了详细说明。

例如:

func (fs FakeService) PrintViaMethod() {
    fs.Client.Print()
}

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

SomeOtherService
2020-07-02