类型构成:覆盖接口类型 [英] Type Composition: overriding interface types

查看:110
本文介绍了类型构成:覆盖接口类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

 包主

导入(
fmt


类型打印机接口{
打印()
}

类型PrinterService结构体{}

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

类型服务struct {
Client PrinterService
}

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

类型FakeService结构{
服务
客户端打印机
}

类型SomeOtherService结构{}

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

func main(){
s:= FakeService {Client:SomeOtherService {}}
s.PrintViaMethod()
}

为什么打印PrinterService?我希望它打印SomeOtherService



谢谢。

s.PrintViaMethod(),您正在调用升级方法 FakeService.Service.PrintViaMethod(),方法接收者将是 FakeService.Service ,它的类型是 Service Service.PrintViaMethod()调用 Service.Client.Print(),其中 Service.Client 的类型是 PrinterService ,这就是它打印PrinterService



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



为了实现你想要的,您必须通过为 FakeService 类型提供实现来覆盖 PrintViaMethod()方法(与 FakeService 接收器类型),并在其中调用 FakeService.Client.Print()



通过这样做 s.PrintViaMethod()将表示 FakeService.PrintViaMethod()方法,因为它将处于 PrintViaMethod()存在的最浅的深度(而不是 FakeService.Service.PrintViaMethod())。详情请参阅规格:选择器



例如:

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

然后输出将会是(在 Go Playground ):

  SomeOtherService 

请参阅相关问题和答案,以获取更多详细信息:

去嵌入结构调用儿童方法,而不是父方法

Go中是否存在易碎的基类问题?


I want to compose a type of another type, but replace one of the fields (which is an interface value) with a fake. The problem I am getting is the underlying field is being used, so I can't seem to override the field.

I've demoed the problem here: 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()
}

Why does it print "PrinterService"? I want it to print "SomeOtherService".

Thanks.

解决方案

By s.PrintViaMethod(), you are calling the promoted method FakeService.Service.PrintViaMethod(), and the method receiver will be FakeService.Service which is of type Service, and Service.PrintViaMethod() calls Service.Client.Print(), where Service.Client is of type which PrinterService, that's why it prints "PrinterService".

In Go there is embedding, but there is no polymorphism. When you embed a type in a struct, methods of the embedded type get promoted and will be part of the method set of the embedder type. But when such a promoted method is called, it will get the embedded value as the receiver, not the embedder.

To achieve what you want, you would have to "override" the PrintViaMethod() method by providing your implementation of it for the FakeService type (with FakeService receiver type), and inside it call FakeService.Client.Print().

By doing so s.PrintViaMethod() will denote the FakeService.PrintViaMethod() method as that will be at the shallowest depth where the PrintViaMethod() exists (and not FakeService.Service.PrintViaMethod()). This is detailed in Spec: Selectors.

For example:

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

Then the output will be (try it on the Go Playground):

SomeOtherService

See related questions and answers with more details:

Go embedded struct call child method instead parent method

Does fragile base class issue exist in Go?

这篇关于类型构成:覆盖接口类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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