C++支持多態,可以通過重載和模板實現多態,其中模板類這個功能我感覺很方便,比如想寫一個棧類型,可以通過模板類,只定義一個類,就能讓這個棧支持int,double,char等多種數據類型。
go語言呢,不支持多態,自然也就沒有模板這個概念,但是沒有關係,go語言的設計者自然知道多態的好處,只是覺得重載這個概念不好理解,所以把多態這個東西給去掉了,取而代之的是一種更簡單的編程方式-接口。
下面我們就來看看,如何使用接口實現C++的模板類。
使用接口實現模板類
首先,我們實現一個int類型的stack。
package mystack
import "errors"
type Mystack []int
func (stack *Mystack) Pop() (int, error) {
if len(*stack) == 0 {
return 0, errors.New("Pop error, stack is empty!")
}
tail := (*stack)[len(*stack)-1]
*stack = (*stack)[:len(*stack)-1]
return tail, nil
}
func (stack *Mystack) Push(val int) {
*stack = append(*stack, val)
}
我們這裏定義了一個Mystack類型,其實就是一個int型切片,放在在mystack包裏,並且定義了兩個方法Push和Pop。接下來我們先看一下效果。
package main
import (
"fmt"
mystack "test/stack"
)
func main() {
stack := mystack.Mystack{1}
fmt.Println(stack)
stack.Push(2)
fmt.Println(stack)
stack.Pop()
fmt.Println(stack)
}
運行結果如下:
歐克,現在我們想讓這個棧支持其他的類型,怎麼辦呢,很簡單,把切片類型由int改爲接口就可以了,剛纔的程序只要改3個地方:
既然改成了“模板類”,那測試函數自然也得搞複雜一些,多整幾種類型。
package main
import (
"fmt"
mystack "test/stack"
)
func main() {
stackInt := mystack.Mystack{1}
stackByte := mystack.Mystack{'a'}
stackString := mystack.Mystack{"abc"}
fmt.Println("origin:", stackInt, stackByte, stackString)
stackInt.Push(2)
stackByte.Push('b')
stackString.Push("efg")
fmt.Println("after push:", stackInt, stackByte, stackString)
stackInt.Pop()
stackByte.Pop()
stackString.Pop()
fmt.Println("after push:", stackInt, stackByte, stackString)
}
運行結果如下:
這結果,對的不能再對了,也就是說,現在我們寫的這個Mystack,已經可以支持int,char,string等所有類型了。
通過把參數類型設置成interface{},我們就實現了將普通類轉化爲模板類,還是很簡單的吧,哈哈~