2016-05-21 89 views
0

,我被弄得實驗用下面的程序,涉及到履行界面結構嵌入,與命名的類型和指針接收器,分別滿足:接口通過結構嵌入

package main 

import "fmt" 

type MyInt interface { 
    mytest() 
} 

type Base struct { 
} 

func (b *Base) mytest() { 
    fmt.Println("From base") 
} 

type Derived struct { 
    Base 
} 

type Derived2 struct { 
    *Base 
} 

func main() { 
    // Only this one has problem 
    // However, if we change mytest's receiver from *Base to Base, all the four assignments are OK 
    var _ MyInt = Derived{} 

    // OK 
    var _ MyInt = &Derived{} 
    var _ MyInt = Derived2{} 
    var _ MyInt = &Derived2{} 
} 

見註釋代碼爲了我的困惑。有沒有解釋它們的主要方法?

回答

1

Go language specification

給定一個結構類型S和一個名爲T型,促進方法包括在該結構的方法集 如下:

  • 如果S包含一個匿名字段T,則S和* S的方法集合均包含用接收器T推廣的方法 。
  • * S的方法集也 包括推廣方法與接收器* T。
  • 如果S包含一個匿名的 字段* T,則S和* S的方法集都包含帶有接收者T或* T的升級方法 。

不會在你的代碼的情況下工作:

var _ MyInt = Derived{} 

這裏Derived方法集(其中包含一個匿名字段Base)包括由規則1. Base方法,因爲mytest*Base而不是Base的方法,它被提升爲*Derived(按第二條規則),但不是Derived的方法。

這是爲什麼?那麼,它與結構方法集的規則類似:T的方法也是T*的方法,但反之亦然。這是因爲指針接收器的方法可以期望能夠改變其接收器,但是非指針接收器的方法不能。

+0

這解釋了它,但我不明白這些規則背後的動機。 –

+0

@ M.Tong我添加了一段話來解釋我認爲動機是什麼。 –

0

根據您的代碼函數mytest可以在接收器上調用指向Base的指針。

結構派生的繼承/嵌入Base和Derived2繼承/嵌入* Base即基指針。

對於

  1. VAR _MyInt = & Derived2的{}:在這裏創建Derived2的指針,自Dervied2從*底座繼承調用mytest的上_MyInt將工作

  2. VAR _MyInt = Derived2的{} :創建了Derived2實例,並且由於Dervied2繼承自_MyInt上的* Base mytest mytest,它將起作用

  3. var _MyInt = & Derived {}:Here Derived的指針創建和自Dervied從基本繼承調用mytest的上_MyInt將工作

  4. VAR _MyInt =衍生{}:將創建的派生實例,自Dervied從基本繼承調用mytest的上_MyInt將無法正常工作具有指針基地有望。

你正確地指出,從*基礎改變接收機基地將工作,因爲圍棋將能夠從指針識別對象,將能夠調用mytest的。

按照golang規範 一個類型可能有一個與之相關的方法集。接口類型的方法集是它的接口。任何其他類型T的方法集由所有使用接收方類型T聲明的方法組成。相應的指針類型* T的方法集是接收方* T或T聲明的所有方法的集合(也包含方法一套T)。

希望這有助於