有关Go语言中多态性的另一个问题,参考:Embedding instead of inheritance in Go,https://medium.com/@adrianwit/abstract-class-reinvented-with-go-4a7326525034
动机:这里有一个接口(带有一些处理“外部世界”的方法)和该接口的许多实现结构。
其中一些方法有一个“标准”实现,其中应将通用逻辑与委托给structs-implementing-the-interface中的(新)方法放在一起(“子类”不是一个词)
我已经阅读了上面的媒体链接,并编写了一些测试代码。 las,它不能按我期望的方式工作,当接口上的调用是间接的时,结构的实际类型会丢失。
在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", "user@foo.com", "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结构,我想在其中实现一些通用代码,这些代码将进一步委托给实现相同接口(“子类不是一个字”)的更多结构中的细粒度方法,类似于:>
https://stackoverflow.com/a/1727737/2342806
问题:
调用command.Execute()
依次调用conn.execute(self)
最终会“切片” Command_Login
对象,并且在Connection.execute
内将其变成Command_Impl
。结果,不会为onData
定义的Command_Login
接口方法被调用。
如果我调用conn.execute(command)
,那么会调用右边的onData
,但这不是我想要连接对象的方式(例如Command
已经有一个{{1} },但基本上是我上面写的关于重用实现的内容。
在Go术语中,我试图提出一种通过嵌入来委托实现的方法,并提供一种使委托回调为封闭类型的方法(可微调委托人的逻辑)。
A,Go似乎不支持它(至少我找不到方法)-将委派给嵌入式结构后,您的调用将完全停留在嵌入式结构中,“不知道”它是一个较大的对象的一部分,该对象可能想要覆盖某些嵌入式struct的方法。
答案 0 :(得分:0)
通过在所需的最浅层实现Execute接口来委派实现呢?
func (self *Command_Login) Execute() {
self.Command_Impl.Execute()
log.Printf("Command Login Execute: %s", reflect.TypeOf(self))
self.onDataCalled = true
}