实际遗失电话

时间:2018-12-31 13:24:56

标签: oop go polymorphism

有关Go语言中多态性的另一个问题,参考:Embedding instead of inheritance in Gohttps://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的方法。

1 个答案:

答案 0 :(得分:0)

通过在所需的最浅层实现Execute接口来委派实现呢?

func (self *Command_Login) Execute() {
    self.Command_Impl.Execute()
    log.Printf("Command Login Execute: %s", reflect.TypeOf(self))
    self.onDataCalled = true
}

https://play.golang.org/p/HvaKHZWIO5W