接口设计的意义
- 泛型编程:使用 interface 可以实现泛型编程
- 隐藏具体实现:设计一个函数返回一个 interface,那么只能通过 interface 里面的方法来做一些操作,但是内部的具体实现是完全不知道的。
golang中的接口
接口定义了一种规范,描述了类的行为和功能,而不做具体实现。
Interface定义了一个或一组method(s),这些method(s)只有函数签名,没有具体的实现代码.
若某个数据类型实现了Interface中定义的那些被称为”methods”的函数,则称这些数据类型实现(implement)了interface。
C++中的接口实现方法
C++ 的接口是使用抽象类来实现的,如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。纯虚函数是通过在声明中使用 “= 0” 来指定的。例如:
1 | class Shape |
设计抽象类的目的:为了给其他类提供一个可以继承的适当的基类。抽象类不能被用于实例化对象,它只能作为接口使用。
派生类需要明确地声明它继承自基类,并且需要实现基类中所有的纯虚函数。
golang接口与C++接口区别
C++ 定义接口的方式称为“侵入式”
Go 采用的是 “非侵入式”,不需要显式声明,只需要实现接口定义的函数,编译器自动会识别。
底层实现不同
- 实现方式:C++ 通过虚函数表来实现基类调用派生类的函数;而 Go 通过
itab
中的fun
字段来实现接口变量调用实体类型的函数。 - 编译生成过程:C++ 中的虚函数表是在编译期生成的;而 Go 的
itab
中的fun
字段是在运行期间动态生成的。原因在于,Go 中实体类型可能会无意中实现 N 多接口,很多接口并不是本来需要的,所以不能为类型实现的所有接口都生成一个itab
, 这也是“非侵入式”带来的影响;这在 C++ 中是不存在的,因为派生需要显示声明它继承自哪个基类。
- 实现方式:C++ 通过虚函数表来实现基类调用派生类的函数;而 Go 通过