以另一种形式实现接口

时间:2012-05-08 07:18:57

标签: inheritance interface struct go base-class

我希望实现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
}

3 个答案:

答案 0 :(得分:2)

转到explicitly declares,这是不可能的:

  

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

对于解决方案,我建议这样的事情:

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) }

答案 1 :(得分: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
}

...

答案 2 :(得分: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))
}