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