类型构成:覆盖接口类型 [英] Type Composition: overriding interface types
问题描述
我想编写另一种类型的类型,但用假的替换其中一个字段(这是一个接口值)。我得到的问题是正在使用的底层字段,所以我似乎无法覆盖该字段。
我在这里演示了这个问题: 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
。
谢谢。
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
请参阅相关问题和答案,以获取更多详细信息:
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屋!