如何扩充系统类型或者别人定义的类型?
一般有三种方法:①使用组合 ②定义别名 ③使用内嵌
1.使用组合 最常用
假设某作者已经在tree包中定义了一个Node类型,现在我们想为这个类型增加一个后序遍历函数postOrder():
import ".../tree"
type myTreeNode struct {
node *tree.Node
}
func (myNode *myTreeNode) postOrder() {
if myNode == nil || myNode.node == nil {
return
}
left := myTreeNode{myNode.node.Left}
right := myTreeNode{myNode.node.Right}
left.postOrder()
right.postOrder()
myNode.node.Print()
}
func main() {
var root tree.Node
root = tree.Node{Value: 3}
root.Left = &tree.Node{}
root.Right = &tree.Node{5, nil, nil}
root.Right.Left = new(tree.Node)
root.Left.Right = tree.CreateNode(2)
root.Right.Left.SetValue(4)
myRoot := myTreeNode{&root}
myRoot.postOrder()
}
2.定义别名 最简单
定义Queue类型,对int切片进行扩展:
package queue
type Queue []int
func (q *Queue) Push(v int) {
*q = append(*q, v)
}
func (q *Queue) Pop() int {
head := (*q)[0]
*q = (*q)[1:]
return head
}
func (q *Queue) IsEmpty() bool {
return len(*q) == 0
}
package main
import (
"queue"
"fmt"
)
func main() {
q := queue.Queue{1}
q.Push(2)
q.Push(3)
fmt.Println(q.Pop()) // 1
fmt.Println(q.Pop()) // 2
fmt.Println(q.IsEmpty()) // false
fmt.Println(q.Pop()) // 3
fmt.Println(q.IsEmpty()) // true
}
3.使用内嵌(Embedding) 节省代码,使代码简洁
import ".../tree"
type myTreeNode struct {
*tree.Node // Embedding(内嵌), 相当于把tree.Node中的变量和方法都给了myTreeNode
}
func (myNode *myTreeNode) postOrder() {
if myNode == nil || myNode.Node == nil {
return
}
left := myTreeNode{myNode.Left}
right := myTreeNode{myNode.Right}
left.postOrder()
right.postOrder()
myNode.Print()
}
func main() {
root := myTreeNode{&tree.Node{Value: 3}}
root.Left = &tree.Node{}
root.Right = &tree.Node{5, nil, nil}
root.Right.Left = new(tree.Node)
root.Left.Right = tree.CreateNode(2)
root.Right.Left.SetValue(4)
root.Traverse() // 0 2 3 4 5
root.postOrder()
}
假设myTreeNode自己再定义一个Traverse()方法:
import ".../tree"
type myTreeNode struct {
*tree.Node // Embedding(内嵌), 相当于把tree.Node中的变量和方法都给了myTreeNode
}
func (myNode *myTreeNode) postOrder() {
if myNode == nil || myNode.Node == nil {
return
}
left := myTreeNode{myNode.Left}
right := myTreeNode{myNode.Right}
left.postOrder()
right.postOrder()
myNode.Print()
}
func (myNode *myTreeNode) Traverse() {
fmt.Println("This method is shadowed.")
}
func main() {
root := myTreeNode{&tree.Node{Value: 3}}
root.Left = &tree.Node{}
root.Right = &tree.Node{5, nil, nil}
root.Right.Left = new(tree.Node)
root.Left.Right = tree.CreateNode(2)
root.Right.Left.SetValue(4)
root.Traverse() // This method is shadowed.
root.Node.Traverse() // 0 2 3 4 5
root.postOrder()
}
如果myTreeNode不自己再定义一个Traverse()方法,那么root.Traverse()来自tree.Node;
如果myTreeNode自己又定义了Traverse()方法,那么root.Traverse()为重新定义的Traverse(),要调用来自tree.Node的Traverse()则需要使用root.Node.Traverse()。