type
status
date
slug
summary
tags
category
icon
password
Sub-item
Last edited time
Oct 15, 2023 02:42 AM
Parent item
领域
struct 嵌入 interface的作用是,继承默认的接口实现方法,同时允许自定义部分接口实现。
interface的动态类型和静态类型
有如下例子:
对于一个接口类型的变量来说,有一个静态类型和动态类型。
例如上面的变量 person,赋给它的值可以被叫做它的实际值(也称动态值),而该值的类型可以被叫做这个变量的实际类型(也称动态类型)。
比如,把取址表达式
&Person
的结果值赋给了变量 person
,值的类型 *Person
就是该变量的动态类型。动态类型这个叫法是相对于静态类型而言的。对于变量 person 来讲,它的静态类型就是 Action,并且永远是 Action,但是它的动态类型却会随着赋给它的动态值而变化。比如,只有我把一个
*Person
类型的值赋给变量 person 之后,该变量的动态类型才会是 *Person
。如果还有一个 Action 接口的实现类型 *ET
,并且我又把一个此类型的值赋给了 person
,那么它的动态类型就会变为 *ET
。在给一个接口类型的变量赋予实际的值之前,它的动态类型是不存在的。
struct嵌入interface
一个实现了某个 interface 的 struct 需要实现该 interface 下的所有方法。
但如果在
struct
中嵌入了一个interface
,例如下面Person
中嵌入了Action
,是可以直接把结构体赋给接口类型的,因为包含了接口方法,但是未实现该方法。Person 确实实现了Action 的方法,从一个更可视化的角度来看,可以看成:
那么
p.Action.Jump()
究竟指代的位置是什么?其实,只要是任何实现了 Action 接口的任何对象都可以。另外需要注意的一点是上述例子的打印结果:
person:size=[16],value=[&{<nil>}]
,这里说明两点:- 一个 interface 占据的大小是 16 个字节;
- 这里 person 的打印结果为
&{<nil>}
,即 Action 接口的打印值为 nil,注意这里 nil 仅代表字面量上的 nil,而不代表此处 Action 的值为 nil,接口在被实例化时,会被包装一层复杂的数据结构 iface,iface 的实例会包含两个指针,一个是指向类型信息的指针,另一个是指向动态值的指针。这里的类型信息是由另一个专用数据结构的实例承载的,其中包含了动态值的类型,以及使它实现了接口的方法和调用它们的途径等等。因此,这里的 nil 的真正含义是指 Action 实例化后指向动态值的指针为 nil。
通过下面这个示例来更清楚的演示细节:
应用
把默认实现了
Action
接口的Somebody
,赋给Hero
嵌入的接口,Hero
自己实现的Jump
方法会把默认Jump
方法覆盖。