go具有浅浅的继承(实现)关系,定义一个结构体,只要实现了某个接口内部的全部方法就可以被认为是实现了该接口,基于此就可以面向对象中的多态。
package Reflect
type inter interface {
print()
}
type School struct {
name string
}
type Address struct {
name string
}
func (s School) print() {
fmt.Println(s.name)
}
func (a Address) print() {
fmt.Println(s.name)
}
如上所示,School结构体以及Address结构体实现了inter接口,基于此可以做如下声明
var p inter=School{"xjtu"}
var pp inter=Address{"xi'an"}
此时变量p的静态类型是inter,而其动态类型为School,前者静态类型不能更改,也就是说不能再做如下声明:var p int。但是后者动态类型可以更改,p=Address{"xi'an"},将p的动态类型改为Address这个是可以的,属于说向下兼容了。
接下来用反射表述一下这个过程
var in inter
fmt.Printf("%T %v\n", in, reflect.TypeOf(&in).Elem())
in = School{"xjtu"}
fmt.Printf("%T %v\n", in, reflect.TypeOf(&in).Elem())
注意reflect.TypeOf(in)获得的是in的动态类型,用fmt包通过%T获取的也是in的动态类型,而reflect.TypeOf(&in).Elem()获取的是in的静态类型。
代码输出为
<nil> Reflect.inter
Reflect.School Reflect.inter
可见一开始没有为in声明实指的时候,其动态类型为nil,静态类型为Reflect.inter,在为其声明了实指为School之后,其动态类型为School,静态类型不变。
ps:p的类型分为静态和动态类型,数据只有一份,在声明in = School{"xjtu"}之后,其数据就指向了School{"xjtu"}