golang中通過組合(composite)實現類似繼承(extends)和重寫(override)的功能,大家可能平時用的比較多的是struct中匿名struct的寫法,有沒有見過struct中匿名接口(anonymous interface)的寫法呢?
Interface這個接口直接作爲struct中的一個匿名字段,在標準庫sort包中就有這種寫法,:
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
type reverse struct {
Interface
}
下面我們來看一個完整的例子,以下代碼是從sort包提取出來的:
package main
import (
"fmt"
)
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
// Array 實現Interface接口
type Array []int
func (arr Array) Len() int {
return len(arr)
}
func (arr Array) Less(i, j int) bool {
return arr[i] < arr[j]
}
func (arr Array) Swap(i, j int) {
arr[i], arr[j] = arr[j], arr[i]
}
// 匿名接口(anonymous interface)
type reverse struct {
Interface
}
// 重寫(override)
func (r reverse) Less(i, j int) bool {
return r.Interface.Less(j, i)
}
// 構造reverse Interface
func Reverse(data Interface) Interface {
return &reverse{data}
}
func main() {
arr := Array{1, 2, 3}
rarr := Reverse(arr)
fmt.Println(arr.Less(0,1))
fmt.Println(rarr.Less(0,1))
}
sort包中這麼寫的目的是爲了重寫Interface的Less方法,並有效利用了原始的Less方法;通過Reverse可以從Interface構造出一個反向的Interface。go語言利用組合的特性,寥寥幾行代碼就實現了重寫。
對比一下傳統的組合匿名結構體實現重寫的寫法,或許可以更好的幫助我們瞭解匿名接口的優點:
package main
import (
"fmt"
)
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
type Array []int
func (arr Array) Len() int {
return len(arr)
}
func (arr Array) Less(i, j int) bool {
return arr[i] < arr[j]
}
func (arr Array) Swap(i, j int) {
arr[i], arr[j] = arr[j], arr[i]
}
// 匿名struct
type reverse struct {
Array
}
// 重寫
func (r reverse) Less(i, j int) bool {
return r.Array.Less(j, i)
}
// 構造reverse Interface
func Reverse(data Array) Interface {
return &reverse{data}
}
func main() {
arr := Array{1, 2, 3}
rarr := Reverse(arr)
fmt.Println(arr.Less(0, 1))
fmt.Println(rarr.Less(0, 1))
}
上面這個例子使用了匿名結構體的寫法,和之前匿名接口的寫法實現了同樣的重寫功能,甚至非常相似。但是仔細對比一下你就會發現匿名接口的優點,匿名接口的方式不依賴具體實現,可以對任意實現了該接口的類型進行重寫。這在寫一些公共庫時會非常有用,如果你經常看一些庫的源碼,匿名接口的寫法應該會很眼熟。