確切地說,go語言也提供了繼承,但是採用了組合的文法,所以我們將其稱為匿名組合:
type base struct
func (base *base) bar()
type foo struct {
base
func (foo *foo) bar() {
foo.base.bar()
以上**定義了乙個base類(實現了foo()和bar()兩個成員方法),然後定義了乙個foo類,該類從base類「繼承」並改寫了bar()方法(該方法實現時先呼叫了基類的bar()方法)。
在「派生類」foo沒有寫「基類」base的成員方法時,相應的方法就被「繼承」,例如在上面的例子中,呼叫foo.foo()和呼叫foo.base.foo()效果一致。
與其他語言不同,go語言很清晰地告訴你的記憶體布局是怎樣的。此外,在go語言中你還可以隨心所欲地修改記憶體布局,如:
type foo struct {
...//其他成員
base
這段**從語義上來說,和上面的例子並無不同,但記憶體布局發生了改變。「基類」base的資料放在了「派生類」foo的最後。
另外,在go語言中,你還可以以指標方式從一類型別「派生」:
type foo struct {
*base
這段go**仍然有「派生」的效果,只是foo建立例項的時候,需要外部提供乙個base類例項的指標。
在c++語言中其實也有類似的功能,那就是虛基類,但是它非常讓人難以理解,一般c++的開發者都會遺忘這個特性。相比之下,go語言以一種非常容易理解的方式提供了一些原本期望用虛基類才能解決的設計難題。
type job struct {
command string
*log.logger
在合適的賦值後,我們在job型別的所有成員方法中可以很舒適地借用所有log.logger提供的方法。比如如下的寫法:
func (job *job) start() {
job.log("starting now...")
...//做一些事情
job.log("started.")
對於job的實現者來說,他甚至根本就不用意識到log.logger型別的存在,這就是匿名組合的魅力所在。在實際工作中,只有合理利用才能最大發揮這個功能的價值。
需要注意的是,不管是非匿名的型別組合還是匿名組合,被組合的型別所包含的方法雖然都公升級了外部這個組合型別的方法,但其實它們被組合的方法呼叫時接收者並沒有改變。比如上面這個job例子,即使組合後呼叫的方式變成了job.log(...),但log函式的接收者仍然是log.logger指標,因此在log中不可能訪問到job的其他成員方法和變數。
這其實也很容易理解,畢竟被組合的型別並不知道自己會被什麼型別組合,當然就沒法在實現方法時去使用那個未知的「組合者」的功能了。
另外,我們必須關注一下介面組合中的名字衝突問題,比如如下的組合:
type x struct {
name string
type y struct {
xname string
組合的型別和被組合的型別都包含乙個name成員,會不會有問題呢?答案是否定的。所有的y型別的name成員的訪問都只會訪問到最外層的那個name變數,x.name變數相當於被隱藏起來了。
那麼下面這樣的場景呢:
type logger struct {
level int
type y struct {
*logger
name string
*log.logger
顯然這裡會有問題。因為之前已經提到過,匿名組合型別相當於以其型別名稱(去掉包名部分)作為成員變數的名字。按此規則,y型別中就相當於存在兩個名為logger的成員,雖然型別不同。因此,我們預期會收到編譯錯誤。
有意思的是,這個編譯錯誤並不是一定會發生的。假如這兩個logger在定義後再也沒有被用過,那麼編譯器將直接忽略掉這個衝突問題,直至開發者開始使用其中的某個logger。
golang匿名組合
一般情況下,定義結構體的時候是欄位名和其型別一一對應,實際上go支援只提供型別而不寫欄位名的方法,也就是匿名字段,也稱為嵌入式字段 當匿名欄位也是乙個結構體的時候,那麼這個結構體所擁有的全部欄位都被隱式的引入了當前定義的這個結構體 實現 復用 type person struct type stud...
Golang中匿名組合實現偽繼承的方法
go語言的物件導向機制與一般語言不同。它沒有類層次結構,甚至可以說沒有類 僅僅通過組合 而不是繼承 簡單的物件來構建複雜的物件。go語言聖經 1.匿名組合 1.1 匿名組合定義 golang中組合語法,就是在乙個類中,引入了另乙個類,如 type logger struct type work st...
Golang中的「繼承」,結構體中匿名成員的使用
最近在看 的時候,看到有結構體中使用匿名成員,在網上查閱一些資料後發現這類似其他語言中的繼承,通過乙個例子簡單總結一下。結構體不多做介紹,這裡直接看匿名成員使用的 示例 type people struct type worker struct我們建立了兩個結構體people和worker,其中wo...