什么是Golang的正交組合-水平組合思維:Tony Bai的博客 - Coding in GO way - Orthogonal Composition
這篇文章研究其中提到的 interface wrapper function司蔬。
//show/show.go
package show
type Shower interface {
Show()
}
這是一個(gè)最簡(jiǎn)單的柴信,定義了一個(gè)Shower的接口并聲明了Show方法东揣,滿足這個(gè)接口的類型Type.Show()
將在屏幕顯示用戶定義的一段文字。
隨后我們需要為這個(gè)Shower接口添加一個(gè)實(shí)例皂股。例如我們添加一個(gè)數(shù)據(jù)類型使他能夠顯示Demo:
user-string
:
//demo/demo.go
package demo
type Show struct {
s string
}
func (this *Show) Show(){
fmt.Println("Demo:",this.s)
}
這段代碼是否應(yīng)該屬于package show
?不是,因?yàn)閷?shí)現(xiàn)Show()方法不止這一種。例如我們還可以:
//demo2/demo.go
package demo2
type Show struct {
s string
}
func (this *Show) Show(){
fmt.Println("This is another Demo: ",this.s)
}
接下來(lái)我們可以在main.go中使用這個(gè)接口和對(duì)應(yīng)的方法:
//main.go
package main
import(
"show"
"demo"
"demo2"
)
func main(){
var ds show.Shower = &demo.Show{"string from main"}
var d2s show.Shower = &demo2.Show{"string from main"}
ds.Show()
}
我們一般用一個(gè)函數(shù)來(lái)包裝參數(shù)愈魏,使之直接返回一個(gè)接口類型。這是interface warp function的其中一種用法:
//demo/demo.go
func NewShow(s string) show.Shower {return &Show{s}}
//demo.Show不是Shower接口的實(shí)現(xiàn)類型想际,*demo.Show才是
在main.go中使用這個(gè)方法來(lái)創(chuàng)建接口:
//main.go
ds := demo.NewShow("string from main")
ds.Show()
注意在寫interface warp的時(shí)候返回類型必須是接口類型培漏,即func NewShow(s string) Show {return &Show{s}}
或func NewShow(s string) *Show {return &Show{s}}
都是錯(cuò)誤的。雖說(shuō)他們或許可以成功執(zhí)行ds.Show()
操作沼琉,但他們都只是一個(gè)結(jié)構(gòu)體北苟,也就是執(zhí)行ds.(show.Shower)
類型斷言時(shí)編譯器會(huì)拋出錯(cuò)誤。
以上都是很基礎(chǔ)的部分打瘪。接下來(lái)我們考慮一個(gè)需求友鼻,即我們需要用一個(gè)方法(接口)來(lái)實(shí)現(xiàn)將字符串連續(xù)打印多遍的功能。例如在stl中LimitedReader
的實(shí)現(xiàn)方法闺骚。為此彩扔,我們創(chuàng)建一個(gè)結(jié)構(gòu)體ShowMultiTimes并繼承Shower:
//which package does it belong??
type ShowMutliTimes_s struct {
n int //n times
}
func (this *ShowMultiTimes_s) Show(){
for i:=0;i<this.n;i++{
//??
}
}
可以發(fā)現(xiàn),這個(gè)方法應(yīng)該同時(shí)對(duì)所有Shower的實(shí)現(xiàn)類型生效僻爽。同時(shí)他打印的內(nèi)容也與Shower的實(shí)現(xiàn)類型(如Demo虫碉,Demo2)有關(guān),因此他應(yīng)該是一個(gè)屬于package show的方法:
package show
import "fmt"
type ShowMultiTimes struct {
S Shower
n int
}
func (this *ShowMultiTimes) Show(){
for i:=0;i<this.n;i++{
fmt.Print("Time",i,": ")
this.S.Show()
}
}
我們說(shuō)interface wrapper function的第二種用法胸梆,即接受interface類型參數(shù)敦捧,并返回與其參數(shù)類型相同的返回值须板。
func ShowNTimes(s Shower, n int) Shower {return &ShowMultiTimes{s,n}}
ShowNTimes是一個(gè)wrapper function,它在s的外面再包裹上ShowMultiTimes兢卵。通過(guò)wrapper function將NewShow和ShowMultiTimes 的兩者巧妙的組合在了一起习瑰。這樣當(dāng)我們采用包裝后的Shower去Read時(shí),輸出的是經(jīng)過(guò)處理后的字符串了秽荤。
//main.go
package main
import(
"show"
"demo"
"demo2"
)
func main(){
st:=show.ShowNTimes(test.NewShowI("String from main"),3)
st.Show()
}
可以看到甜奄,interface warp function可以組合成一個(gè)chain,因?yàn)槠鋡rapper function返回值類型與parameter類型相同窃款。