2

我希望实现fmt.Stringer接口的String方法。但是,对于从 派生的一组类型Node,它们的String实现将是围绕Print它们必须提供的接口方法的包装器。如何String自动提供所有类型的实现Node?如果我String在某些基类上提供默认值,我将无法访问派生类型(以及接口方法Print)。

type Node interface {
    fmt.Stringer
    Print(NodePrinter)
}

type NodeBase struct{}

func (NodeBase) String() string {
    np := NewNodePrinter()
    // somehow call derived type passing the NodePrinter
    return np.Contents()
}

type NodeChild struct {
    NodeBase
    // other stuff
}

func (NodeChild) Print(NodePrinter) {
    // code that prints self to node printer
}
4

3 回答 3

2

Go明确声明这是不可能的:

当我们嵌入一个类型时,该类型的方法成为外部类型的方法,但是当它们被调用时,方法的接收者是内部类型,而不是外部类型。

对于解决方案,我推荐这样的东西:

func nodeString(n Node) string {
    np := NewNodePrinter()
    // do stuff
    n.Print(np)
    return np.Contents()
}

// Now you can add String method to any Node in one line
func (n NodeChild) String() string { return nodeString(n) }
于 2012-05-08T08:28:01.373 回答
0

在 Go 语言中,不支持获取对象 ( NodeChild) 的包含对象 ( NodeBase)。但是您可以自己实现此功能:

type Node interface {
    fmt.Stringer
    Print(NodePrinter)
}

type NodeBase struct {
    Self Node
}

func (n NodeBase) String() string {
    np := NewNodePrinter()
    n.Self.Print(np)
    return np.Contents()
}

type NodeChild struct {
    NodeBase
    // other stuff
}

func NewNodeChild() *NodeChild {
    var n NodeChild
    n.Self = &n
    return &n
}

func (*NodeChild) Print(NodePrinter) {
    // code that prints self to node printer
}

更普遍:

type Object struct {
    Self interface{}
}

type NodeBase struct {
    Object
}

...
于 2012-05-08T09:03:11.713 回答
0

如果您希望它对未来的更改更加灵活,即如果您的节点对象需要不同的代码来打印自己并且您有一些通用的打印代码,并且您希望具有可插入性,请考虑以下事项:

package main 

type printableNode struct{
    // define whatever a printer needs to be able to print a node
}

type Node interface {
    // or return some other type that can be handled by NodePrinter
    Printable() printableNode
}

type NodeBase struct{}

// printable representation of a nodebase
func (nb NodeBase) Printable() printableNode {
}

type NodeChild struct {
    NodeBase
    // other stuff
}

//  may make use of nc.Nodebase.Printable()
func (nc NodeChild) Printable() printableNode {
}

type Print struct{Node}

// do the common stuff, in other places you may define other printers
// this way
func (pr Print) String() string {
    // do something with pr.Node.Printable() and return a string
}

// you may also use a simple function that receives a node and returns a string
func Print2(n Node) string {
   // do something with n.Printable() and return a string
}


func main() {
    nb := Nodebase{}
    // use it to print
    fmt.Println(Print{nb})
    // or (simpler)
    fmt.Println(Print2(nb))
}
于 2013-07-30T13:27:03.690 回答