確切地說,Go語言也提供了繼承,但是采用了組合的文法,所以我們將其稱為匿名組合:
type Base struct {
Name string
}
func (base *Base) Foo() {...}
func (base *Base) Bar() {...}
type Foo struct {
Base
...
}
func (foo *Foo) Bar() {
foo.Base.Bar()
...
}
以上代碼定義了一個(gè)Base類(實(shí)現(xiàn)了Foo()和Bar()兩個(gè)成員方法),然后定義了一個(gè)Foo類,該類從Base類“繼承”并改寫了Bar()方法(該方法實(shí)現(xiàn)時(shí)先調(diào)用了基類的Bar()方法)。
在“派生類”Foo沒有寫“基類”Base的成員方法時(shí),相應(yīng)的方法就被“繼承”,例如在上面的例子中,調(diào)用foo.Foo()和調(diào)用foo.Base.Foo()效果一致。
與其他語言不同,Go語言很清晰地告訴你的內(nèi)存布局是怎樣的。此外,在Go語言中你還可以隨心所欲地修改內(nèi)存布局,如:
type Foo struct {
...//其他成員
Base
}
這段代碼從語義上來說,和上面的例子并無不同,但內(nèi)存布局發(fā)生了改變?!盎悺盉ase的數(shù)據(jù)放在了“派生類”Foo的最后。
另外,在Go語言中,你還可以以指針方式從一類類型“派生”:
type Foo struct {
*Base
...
}
這段Go代碼仍然有“派生”的效果,只是Foo創(chuàng)建實(shí)例的時(shí)候,需要外部提供一個(gè)Base類實(shí)例的指針。
在C++語言中其實(shí)也有類似的功能,那就是虛基類,但是它非常讓人難以理解,一般C++的開發(fā)者都會(huì)遺忘這個(gè)特性。相比之下,Go語言以一種非常容易理解的方式提供了一些原本期望用虛基類才能解決的設(shè)計(jì)難題。
在Go語言官方網(wǎng)站提供的Effective Go中曾提到匿名組合的一個(gè)小價(jià)值,值得在這里再提一下。首先我們可以定義如下的類型,它匿名組合了一個(gè)log.logger指針:
type Job struct {
Command string
*log.Logger
}
在合適的賦值后,我們在Job類型的所有成員方法中可以很舒適地借用所有l(wèi)og.Logger提供的方法。比如如下的寫法:
func (job *Job) Start() {
job.Log("starting now...")
...//做一些事情
job.Log("started.")
}
對于Job的實(shí)現(xiàn)者來說,他甚至根本就不用意識(shí)到log.logger類型的存在,這就是匿名組合的魅力所在。在實(shí)際工作中,只有合理利用才能大發(fā)揮這個(gè)功能的價(jià)值。
需要注意的是,不管是非匿名的類型組合還是匿名組合,被組合的類型所包含的方法雖然都升級(jí)了外部這個(gè)組合類型的方法,但其實(shí)它們被組合的方法調(diào)用時(shí)接收者并沒有改變。比如上面這個(gè)Job例子,即使組合后調(diào)用的方式變成了job.Log(...),但Log函數(shù)的接收者仍然是log.Logger指針,因此在Log中不可能訪問到j(luò)ob的其他成員方法和變量。
這其實(shí)也很容易理解,畢竟被組合的類型并不知道自己會(huì)被什么類型組合,當(dāng)然就沒法在實(shí)現(xiàn)方法時(shí)去使用那個(gè)未知的“組合者”的功能了。
另外,我們必須關(guān)注一下接口組合中的名字沖突問題,比如如下的組合:
type X struct {
Name string
}
type Y struct {
X
Name string
}
組合的類型和被組合的類型都包含一個(gè)Name成員,會(huì)不會(huì)有問題呢?答案是否定的。所有的Y類型的Name成員的訪問都只會(huì)訪問到最外層的那個(gè)Name變量,X.Name變量相當(dāng)于被隱藏起來了。
那么下面這樣的場景呢:
type Logger struct {
level int
}
type Y struct {
*Logger
Name string
*log.Logger
}
顯然這里會(huì)有問題。因?yàn)橹耙呀?jīng)提到過,匿名組合類型相當(dāng)于以其類型名稱(去掉包名部分)作為成員變量的名字。按此規(guī)則,Y類型中就相當(dāng)于存在兩個(gè)名為Logger的成員,雖然類型不同。因此,我們預(yù)期會(huì)收到編譯錯(cuò)誤。
有意思的是,這個(gè)編譯錯(cuò)誤并不是一定會(huì)發(fā)生的。假如這兩個(gè)Logger在定義后再也沒有被用過,那么編譯器將直接忽略掉這個(gè)沖突問題,直至開發(fā)者開始使用其中的某個(gè)Logger。
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開啟,新人活動(dòng)云服務(wù)器買多久送多久。
網(wǎng)站題目:golang中的匿名組合-創(chuàng)新互聯(lián)
路徑分享:http://chinadenli.net/article8/dcjsip.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、網(wǎng)站維護(hù)、搜索引擎優(yōu)化、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站改版、網(wǎng)站設(shè)計(jì)公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容