【高级数据类型2】- 10. 接口

Go语言-接口

    在Go语言中,一个接口类型老是表明着某一种类型(即全部实现它的类型)的行为。一个接口类型的声明一般会包含关键字type、类型名称、关键字interface以及由花括号包裹的若干方法声明。示例以下:编程

type Animal interface {
    Grow()
    Move(string) string
}

    注意,接口类型中的方法声明是普通的方法声明的简化形式。它们只包括方法名称、参数声明列表和结果声明列表。其中的参数的名称和结果的名称均可以被省略。不过,出于文档化的目的,我仍是建议你们在这里写上它们。所以,Move方法的声明至少应该是这样的:并发

Move(new string) (old string)

    若是一个数据类型所拥有的方法集合中包含了某一个接口类型中的全部方法声明的实现,那么就能够说这个数据类型实现了那个接口类型。所谓实现一个接口中的方法是指,具备与该方法相同的声明而且添加了实现部分(由花括号包裹的若干条语句)。相同的方法声明意味着彻底一致的名称、参数类型列表和结果类型列表。其中,参数类型列表即为参数声明列表中除去参数名称的部分。一致的参数类型列表意味着其长度以及顺序的彻底相同。对于结果类型列表也是如此。
  
    例如,若是你正确地完成了上一小节的练习的话,*Person类型(注意,不是Person类型)就会拥有一个Move方法。该方法会是Animal接口的Move方法的一个实现。再加上咱们在以前为它编写的那个Grow方法,*Person类型就能够被看作是Animal接口的一个实现类型了。
  
    你可能已经意识到,咱们无需在一个数据类型中声明它实现了哪一个接口。只要知足了“方法集合为其超集”的条件,就创建了“实现”关系。这是典型的无侵入式的接口实现方法。
  
    好了,如今咱们已经认为*Person类型实现了Animal接口。可是Go语言编译器是否也这样认为呢?这显然须要一种显式的断定方法。在Go语言中,这种断定能够用类型断言来实现。不过,在这里,咱们是不能在一个非接口类型的值上应用类型断言来断定它是否属于某一个接口类型的。咱们必须先把前者转换成空接口类型的值。这又涉及到了Go语言的类型转换。
  
    Go语言的类型转换规则定义了是否可以以及怎样能够把一个类型的值转换另外一个类型的值。另外一方面,所谓空接口类型便是不包含任何方法声明的接口类型,用interface{}表示,常简称为空接口。正由于空接口的定义,Go语言中的包含预约义的任何数据类型均可以被看作是空接口的实现。咱们能够直接使用类型转换表达式把一个*Person类型转换成空接口类型的值,就像这样:spa

p := Person{"Robert", "Male", 33, "Beijing"}
v := interface{}(&p)

    请注意第二行。在类型字面量后跟由圆括号包裹的值(或可以表明它的变量、常量或表达式)就构成了一个类型转换表达式,意为将后者转换为前者类型的值。在这里,咱们把表达式&p的求值结果转换成了一个空接口类型的值,并由变量v表明。注意,表达式&p&是取址操做符)的求值结果是一个*Person类型的值,即p的指针。
  
    在这以后,咱们就能够在v上应用类型断言了,即:指针

h, ok := v.(Animal)

    类型断言表达式v.(Animal)的求值结果能够有两个。第一个结果是被转换后的那个目标类型(这里是Animal)的值,而第二个结果则是转换操做成功与否的标志。显然,ok表明了一个bool类型的值。它也是这里断定实现关系的重要依据。
  
    至此,咱们掌握了接口类型、实现类型以及实现关系断定的重要知识和技巧。关于Go语言的类型转换规则的更多细节请参看Go语言规范或《Go并发编程实战》中的相关内容。而至于为何只有*Person类型才实现了Animal接口,请参看后面两节。code

相关文章
相关标签/搜索