2

我目前正在玩一些 go 代码,并且遇到了一个涉及嵌入的小问题,我找不到满意的答案。给定两种类型,其中一种嵌入另一种,并且满足接口,我希望嵌入类型能够反映嵌入器的属性以提供默认响应,这样对象就不必定义接口中的所有方法,除非它们想要覆盖。

在下面的玩具示例中,我希望能够在嵌入式上定义一个 hello() 函数,它处理默认情况并只返回 Name (注意这是一个玩具示例,实际代码更复杂和有用),没有要求对象明确定义接口上的所有方法。真正的代码使用反射来判断对象类型的类名和构造名称,目前我正在调用基类助手,传入该类型的实例,但这并不令人满意。

package main
type MyInterface interface {
    hello() string
    //...
}

type Embedded struct {

}

func (e *Embedded) hello() string {
    name := "none"
    // Would like to be able to return name of object here *if* embedded
    // What's the best approach to tackle this?

    return name
}


type Object struct {
    *Embedded
    Name    string
}

/*
// Would like an *optional* override, with default being embedded somehow replying with data from Object
func (o *Object) hello() string {
    return o.Name
}
*/


func main() {
    o := &Object{Name:"My Object Name"}
    println("Hello world",o.hello())
}

在 goplay 上:

http://play.golang.org/p/ClOOCef9Zb

我很想听听 Go 中针对此类问题的其他解决方案(提供使用嵌入类属性的默认函数)以及针对此特定问题的解决方案(如果有的话)。到目前为止,我唯一的解决方案是:

要求在满足此接口的所有类型上重新定义方法 hello(),并放弃拥有提供默认方法的“基”类 使用指向对象实例的指针调用嵌入式帮助函数,因此类型可以大部分为空方法调用嵌入式类型。

如果有完全不同的方法在 Go 中很有价值并且不尝试复制我有兴趣了解它们的继承模型,那么到目前为止,这是我在继承中唯一错过的一次......

4

2 回答 2

2

方法的接收者是 / 指的是相应类型 T 的实例。没有语言支持的方式如何获取有关嵌入的 T 的任何信息,例如在执行 T 的方法时的 U:

type (
        T foo
        U struct {
                t T
                f baz
        }
)

func bar() {
        var t T
        var u U
        t.foo()
        u.t.foo()
}

func (t T) foo()  {} // t might be or be not embeded in u
func (t *T) qux() {} // *t might be or be not embeded in u

您可能正在尝试使用结构继承。这是不支持的。通过嵌入可以组合类型,但这与类层次结构不同。

OTOH,Go 接口支持继承和方法覆盖,所以这可能是方式。请注意,在这种情况下,继承是行为的,而不是结构的。

于 2013-03-17T11:49:50.640 回答
0

为了解决这个问题,我决定放弃 ersatz 继承,并指定模型需要在接口中共享的信息(这里缺少字段的自动属性访问器有点烦人,上面的对象必须显式导出这些以允许任何传递 MyInterface 引用以使用它们的人,字段 Name 是公共的,但即使在接口上定义了 Name() 字符串也无法访问)。

然后模型调用另一个包中的辅助函数,并将自己作为有用的参数提供,并且由于它符合 MyInterface 它可以以这种方式进行询问。所以它(和其他类似的 MyInterface 对象)可以使用它们的公共信息完成复杂的操作并充当外观。显然,在上面的简单示例中,这是没有意义的,但我想在几个 MyInterface 类型之间共享包中的代码,现在将采用这种方法而不是嵌入。

因此,正如上面 jnml 所指出的,我在这里的主要收获是,嵌入对于混合依赖于实例状态的函数没有用,也不能直接替代继承层次结构中的基类。如果你已经使用 Go 一段时间了,也许很明显......

于 2013-03-18T23:13:19.187 回答