2016-05-21 57 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)。

希望这有助于