当前位置: > > > > 实际类型在调用时丢失
实际类型在调用时丢失
来源:stackoverflow
2024-04-30 14:27:35
0浏览
收藏
IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天米云给大家整理了《实际类型在调用时丢失》,聊聊,我们一起来看看吧!
问题内容
另一个关于 go 中多态性的问题,参考:go 中的嵌入而不是继承,https://medium.com/@adrianwit/abstract-class-reinvented-with-go-4a7326525034
动机:有一个接口(带有一些处理“外部世界”的方法)和该接口的一堆实现结构。
其中一些方法有一个“标准”实现,其中公共逻辑应该放在一个地方,并委托给结构实现接口中的(新)方法(“子类”不是一个词) .
我已阅读上面的中等链接并编写了一些测试代码。唉,它没有按照我期望的方式工作,当接口上的调用是间接的时,结构的实际类型会丢失。
在 c++ 中,这称为“基类切片”,在按值传递多态类时发生。在我的 go 测试代码中,我小心地通过引用传递,然后 go 就不是 c++(或 java)。
代码:https://play.golang.org/p/lxamw8v_kiw
内联:
package main
import (
"log"
"reflect"
"strings"
)
// Command - interface
type Command interface {
Execute()
getCommandString() string
onData(data string)
}
// Command - implementation
type Command_Impl struct {
commandString string
conn Connection
}
func newCommand_Impl(conn Connection, data string, args ...string) Command_Impl {
var buf strings.Builder
buf.WriteString(data)
for _, key := range args {
buf.WriteString(" ")
buf.WriteString(key)
}
return Command_Impl {
conn: conn,
commandString: buf.String(),
}
}
func (self *Command_Impl) Execute() {
log.Printf("Command Impl Execute: %s", reflect.TypeOf(self))
self.conn.execute(self)
}
func (self *Command_Impl) getCommandString() string {
return self.commandString
}
func (self *Command_Impl) onData(data string) {
log.Printf("Command Impl onData: %s", data)
}
// Command - subclass
type Command_Login struct {
Command_Impl
onDataCalled bool
}
func newCommand_Login(conn Connection) *Command_Login {
return &Command_Login{
Command_Impl: newCommand_Impl(conn, "LOGIN", "[email protected]", "pa$$w0rd"),
}
}
func (self *Command_Login) onData(data string) {
log.Printf("Command Login onData: %s", data)
self.onDataCalled = true
}
// Connection - interface
type Connection interface {
execute(command Command)
}
// Connection - impelementation
type Connection_Impl struct {
}
func newConnection_Impl() *Connection_Impl {
return &Connection_Impl{}
}
func (self *Connection_Impl) execute(command Command) {
log.Printf("Connection execute: %s, %s", command.getCommandString(), reflect.TypeOf(command))
command.onData("some data")
}
func main() {
conn := newConnection_Impl()
command := newCommand_Login(conn)
// I expect command.Execute to preserve actual type of command all the way through
// command.conn.execute(self) and then the callback onData from connection to command
// to use the onData in Command_Login
//
// This does not happen however, the test fails
command.Execute()
// This does preserve actual type of command, but isn't how I'd like to connect
// commands and connections...
//
//conn.execute(command)
if command.onDataCalled {
log.Printf("*** GOOD: Command_Login onData ***was*** called")
} else {
log.Printf("*** ERROR: Command_Login onData ***not*** called")
}
}
有一个 command 接口,它定义了一些方法。
有一个 command_impl 结构,我想在其中实现一些通用代码,这些代码将进一步委托给实现相同接口的更多结构中的更细粒度的方法(“子类不是一个单词”),类似于: p>
https://stackoverflow.com/a/1727737/2342806
问题:
调用 command.execute() 又调用 conn.execute(self) 最终“切片”command_login 对象,并在 connection.execute 内将其转换为 command_impl。因此,为 command_login 定义的 ondata 接口方法不会被调用。
如果我调用 conn.execute(command) 那么正确的 ondata 确实会被调用,但这不是我想要连接我的对象的方式(例如 command 已经有一个 connection ,但基本上是我上面写的关于重用的内容实施)。
用 go 术语来说,我试图想出一种通过嵌入来委托实现的方法,并有一种方法让委托回调到封闭类型 em> (微调委托的逻辑)。
唉,go 似乎不支持它(至少我找不到方法)——一旦你委托给嵌入结构,你的调用就完全保留在嵌入结构中,它“不知道”它是一个较大对象的一部分,该对象可能想要覆盖某些嵌入结构的方法。
解决方案
通过在您需要的最浅深度实现 execute 接口来委托实现怎么样?
func (self *Command_Login) Execute() {
self.Command_Impl.Execute()
log.Printf("Command Login Execute: %s", reflect.TypeOf(self))
self.onDataCalled = true
}
今天关于《实际类型在调用时丢失》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注米云公众号!
