结构嵌入实现了接口

时间:2016-05-21 11:08:24

标签: go

我对以下程序的实验感到困惑,该程序涉及使用结构嵌入实现接口,分别使用命名类型和指针接收器:

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{}
}

请参阅代码中的注释以了解我的困惑。是否有任何主要方法来解释它们?

2 个答案:

答案 0 :(得分:1)

来自Go language specification

  

给定结构类型S和名为T的类型,提升的方法是   包含在结构的方法集中,如下所示:

     
      
  • 如果S包含匿名字段T,则方法设置为S和* S.   包括与接收者T的推广方法。
  •   
  • * S的方法集也   包括带接收器* T的推广方法。
  •   
  • 如果S包含匿名   field * T,S和* S的方法集都包括提升方法   接收器T或* T。
  •   

在您的代码中不起作用的情况:

var _ MyInt = Derived{}

此处Derived的方法集(包含匿名字段Base)包含规则1的Base方法。因为mytest是{{1}的方法而不是*Base,它被提升为Base(第二条规则)的方法,而不是*Derived的方法。

为什么会那样?嗯,它类似于结构方法集的规则:Derived的方法也是T的方法,但反之亦然。这是因为指针接收器的方法可以期望能够改变其接收器,但是非指针接收器的方法可能不会。

答案 1 :(得分:0)

根据你的代码函数,mytest可以在接收器上调用,指针指向Base。

Struct Derived继承/嵌入Base和Derived2继承/嵌入* Base,即指向base的指针。

对于

  1. var _MyInt =& Derived2 {}:这里创建Derived2的指针,因为Dervied2继承自* Base,_MyInt调用mytest将起作用

  2. var _MyInt = Derived2 {}:Derived2的实例已创建,因为Dervied2继承自* Base,_MyInt调用mytest将起作用

  3. var _MyInt =& Derived {}:这里创建了Derived的指针,因为Dervied继承自Base调用_MyInt上的mytest将起作用

  4. var _MyInt = Derived {}:Derived的实例已创建,并且由于Dervied继承自Base调用mytest on _MyInt将无法使用指向Base的指针。

  5. 你正确地指出将接收器从* Base更改为Base将起作用,因为Go将能够从指针识别Object并且能够调用mytest。

    根据golang规范 类型可以具有与其关联的方法集。接口类型的方法集是其接口。任何其他类型T的方法集由用接收器类型T声明的所有方法组成。相应指针类型* T的方法集是用receiver * T或T声明的所有方法的集合(也就是说,它还包含方法一套T)。

    希望这有帮助