类型组合:覆盖接口类型
Type Composition: overriding interface types
我想将一种类型组合成另一种类型,但将其中一个字段(这是一个接口值)替换为假的。我遇到的问题是正在使用基础字段,所以我似乎无法覆盖该字段。
我在这里演示了这个问题: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"
.
谢谢。
Why does it print 'PrinterService'? I want it to print 'SomeOtherService'.
因为这就是您的代码要求执行的操作。 PrintViaMethod
调用 s.Client.Print()
,s.Client
是 PrinterService
的(零值)实例,它输出 PrinterService
.
您可能想要在 main()
中调用 s.Print()
。我完全看不出你的 PrintByMethod
函数有任何理由。
通过 s.PrintViaMethod()
,您正在调用 promoted 方法 FakeService.Service.PrintViaMethod()
,方法接收者将是 FakeService.Service
,类型为 Service
,并且 Service.PrintViaMethod()
调用 Service.Client.Print()
,其中 Service.Client
是 PrinterService
的类型,这就是它打印 "PrinterService"
.
的原因
Go 中有 embedding, but there is no polymorphism。当您在结构中嵌入类型时,嵌入类型的方法得到提升,并将成为嵌入类型方法集的一部分。但是当这样一个提升的方法被调用时,它会得到嵌入值作为接收者,而不是嵌入者。
要实现您想要的效果,您必须通过为 FakeService
类型(使用 FakeService
接收器类型)提供 PrintViaMethod()
方法的实现来实现 "override" PrintViaMethod()
方法), 并在其中调用 FakeService.Client.Print()
.
这样做 s.PrintViaMethod()
将表示 FakeService.PrintViaMethod()
方法,因为它将位于 PrintViaMethod()
存在的最浅深度(而不是 FakeService.Service.PrintViaMethod()
)。这在 Spec: Selectors.
中有详细说明
例如:
func (fs FakeService) PrintViaMethod() {
fs.Client.Print()
}
然后输出将是(在Go Playground上试试):
SomeOtherService
更多详细信息请参阅相关问题和答案:
根据 Flimzy
,您正在调用 print s.Client.Print()
,它的类型 PrinterService
实现为 Print()
函数打印 PrinterService
的接收方。您还可以将 Service
结构中 Client
PrinterService
的类型更改为 Someother service
package embedded
import (
"fmt"
)
type Printer interface {
Print()
}
type PrinterService struct{}
func (ps PrinterService) Print() { fmt.Println("PrinterService") }
type Service struct {
Client SomeOtherService
}
func (s Service) PrintViaMethod() { s.Client.Print() }
type FakeService struct {
Service
Client Printer
}
type SomeOtherService struct{}
func (sos SomeOtherService) Print() { fmt.Println("SomeOtherService") }
func Call() {
s := FakeService{Client: SomeOtherService{}}
s.PrintViaMethod()
}
我想将一种类型组合成另一种类型,但将其中一个字段(这是一个接口值)替换为假的。我遇到的问题是正在使用基础字段,所以我似乎无法覆盖该字段。
我在这里演示了这个问题: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"
.
谢谢。
Why does it print 'PrinterService'? I want it to print 'SomeOtherService'.
因为这就是您的代码要求执行的操作。 PrintViaMethod
调用 s.Client.Print()
,s.Client
是 PrinterService
的(零值)实例,它输出 PrinterService
.
您可能想要在 main()
中调用 s.Print()
。我完全看不出你的 PrintByMethod
函数有任何理由。
通过 s.PrintViaMethod()
,您正在调用 promoted 方法 FakeService.Service.PrintViaMethod()
,方法接收者将是 FakeService.Service
,类型为 Service
,并且 Service.PrintViaMethod()
调用 Service.Client.Print()
,其中 Service.Client
是 PrinterService
的类型,这就是它打印 "PrinterService"
.
Go 中有 embedding, but there is no polymorphism。当您在结构中嵌入类型时,嵌入类型的方法得到提升,并将成为嵌入类型方法集的一部分。但是当这样一个提升的方法被调用时,它会得到嵌入值作为接收者,而不是嵌入者。
要实现您想要的效果,您必须通过为 FakeService
类型(使用 FakeService
接收器类型)提供 PrintViaMethod()
方法的实现来实现 "override" PrintViaMethod()
方法), 并在其中调用 FakeService.Client.Print()
.
这样做 s.PrintViaMethod()
将表示 FakeService.PrintViaMethod()
方法,因为它将位于 PrintViaMethod()
存在的最浅深度(而不是 FakeService.Service.PrintViaMethod()
)。这在 Spec: Selectors.
例如:
func (fs FakeService) PrintViaMethod() {
fs.Client.Print()
}
然后输出将是(在Go Playground上试试):
SomeOtherService
更多详细信息请参阅相关问题和答案:
根据 Flimzy
,您正在调用 print s.Client.Print()
,它的类型 PrinterService
实现为 Print()
函数打印 PrinterService
的接收方。您还可以将 Service
结构中 Client
PrinterService
的类型更改为 Someother service
package embedded
import (
"fmt"
)
type Printer interface {
Print()
}
type PrinterService struct{}
func (ps PrinterService) Print() { fmt.Println("PrinterService") }
type Service struct {
Client SomeOtherService
}
func (s Service) PrintViaMethod() { s.Client.Print() }
type FakeService struct {
Service
Client Printer
}
type SomeOtherService struct{}
func (sos SomeOtherService) Print() { fmt.Println("SomeOtherService") }
func Call() {
s := FakeService{Client: SomeOtherService{}}
s.PrintViaMethod()
}