2012-05-08 48 views
2

我希望實現fmt.Stringer接口的String方法。然而,對於衍生自Node的一組類型,它們的String實現將圍繞它們必須提供的接口方法進行包裝。我如何自動爲所有類型的Node提供String?如果我在某些基類上提供默認的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 
} 

回答

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

Mostafa,這是我目前正在解決它。看到你找到同樣的解決方案真是令人振奮。 –

+0

@MattJoiner那麼,這似乎是最合乎邏輯的,至少對我來說。很高興幫助。 – Mostafa

0

在Go語言有用於獲取到的物體(NodeBase)的包含對象(NodeChild)不支持。但是你可以自己實現這個功能:

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 
} 

... 
+0

一個不錯的主意,但太混亂。 –

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