接口与反射
接口
定义
接口定义了一组方法(方法集),但是这些方法不包含(实现)代码,接口里也不能包含变量。
通过如下格式定义接口:
type InterfaceName interface {
Method1(param_list) return_type
Method2(param_list) return_type
...
}
范例,将形状的面积方法抽取出来作为抽象接口:
type Shaper interface {
Area() float64
}
type Square struct {
side float64
}
func (s *Square) Area() float64 { // 实现抽象接口
return s.side*s.side
}
调用:
sq1 := new(Square)
sq1.side = 10
var shp Shaper = sq1 // 获取结构体对应的抽象接口
fmt.Printf("\t正方形边长: %f,面积: %f\n", sq1.side, shp.Area())
上面的代码中var shp Shaper = sq1
实现了从结构体到接口类型的转化,shp中保存了对该对象的引用,使用这种方式就可以实现面向对象的多态。
将结构体转化成接口的前提是:该结构体实现了接口中所有的方法!
判断接口持有者的类型(向下转换)
在使用面向对象语言时,经常需要判断持有抽象接口的对象类型,这样就可以进行向下转换
,Go语言提供了同样的功能:
v, ok := varIntf.(T); // T表示被绑定的类型
通过上述接口,可以判断该接口绑定的对象类型,例如判断一个Shaper
接口是不是Square
:
if v,ret := shp.(*Square); ret {
fmt.Printf("\t该Shaper接口绑定的是Square类型:%v\n", v);
}
这里与可以使用switch
的type来判定:
switch t := shp.(type) {
case *Square:
fmt.Printf("\tType Square %T with value %v\n", t, t)
default:
fmt.Printf("\tUnexpected type %T\n", t)
}
空接口
任何其他类型都实现了空接口(它不仅仅像 Java/C# 中 Object 引用类型),any 或 Any 是空接口一个很好的别名或缩写。
空接口类似 Java/C# 中所有类的基类: Object 类,二者的目标也很相近。可以给一个空接口类型的变量 var val interface {} 赋任何类型的值。
空接口定义范例:
type Any interface{}