GObject参考手册(7)--不可实例的类型:接口
2008-12-14 20:02
429 查看
本文引用自http://imtx.cn,原文作者:TualatriX
原文:http://library.gnome.org/devel/gobject/2.14/gtype-instantiable-classed.html
GType的接口(Interface)与Java的接口非常类似。它允许描述一个通用的API,使得多个类可以粘合在一起。想像一下,Hi-Fi音响设备中的暂停和播放按钮──这可以被视做一个回放接口。如果你知道你要做什么,你可以用来这个接口来控制你的CD机,MP3或其他使用相同符号的东西。要声明一个接口,你需要注册一个从GTypeInterface继承的不可实例的类型。下面的代码声明了这样的一个接口:
这里用非常简单的方法来实现maman_ibaz_do_action这个接口函数:
maman_ibaz_get_type注册了一个从G_TYPE_INTERFACE继承的名为MamanIBaz的类型。在继承树中,所有的接口必须是G_TYPE_INTERFACE的子类。
一个接口只有一个包含GTypeInterface的结构来定义。接口的结构应该要包含一个函数指针指向这个接口的方法。用类似于maman_ibaz_do_action的方法在每个接口方法中定义帮助函数,可以使得我们直接调用接口方法,这是一个良好的风格。
一旦一个接口的类型被注册后,你必须来实现这个接口。其中,命名为maman_baz_get_type注册一个名为MamanBaz的由GObject继承来的新的GType,并在接口Interface中实现。
g_type_add_interface_static记录了在类型系统中如FooInterface来实现的接口(foo_interface_get_type返回FooInterface的类型),GInterfaceInfo保存着关于接口实现的信息:
首先为接口结构分配内存缓冲,父接口结构先被复制(父接口先被初始化)。如果没有父接口,接口结构将由0初始化。g_type和g_instance_type将在其后被初始化:g_type被设置为最先起源的接口,g_instance_type被设置为最先起源的实现这个接口的类。
最终,接口的最顶层的base_init函数和实现接口的interface_init被调用。了解下面是重要的:如果有一个接口有多个base_init和interface_init的实现,那么每个实现都被调用一次以初始化。
base_init函数保持了一个本地静态变量用来确保这个接口类型只被初始化一次而不管它是否被实现了几次:
如果你发现接口很烦,确实如此。它确实很烦,但是我也没办法啊。我只有把接口的过程归纳一下了!
type_iface_vtable_finalize_Wm调用了第一个实现的interface_finalize函数,接着是接口最底层的base_finalize函数。
同样,下面的理解非常重要,如“接口的初始化”中描述的,interface_finalize和base_finalize都将被调用来确保一个接口的实现被正确的销毁。例如,如果你曾用过其中一个函数,你将需要使用一个静态的整形来保持有关实例实现的接口的数量,这样接口的类才会只被销毁一次(当整型变量为0时)。
上面的处理过程总结如下:
你已经读完了这章,现在你可以忘记它了。请尽可能快地忘记它!
原文:http://library.gnome.org/devel/gobject/2.14/gtype-instantiable-classed.html
GType的接口(Interface)与Java的接口非常类似。它允许描述一个通用的API,使得多个类可以粘合在一起。想像一下,Hi-Fi音响设备中的暂停和播放按钮──这可以被视做一个回放接口。如果你知道你要做什么,你可以用来这个接口来控制你的CD机,MP3或其他使用相同符号的东西。要声明一个接口,你需要注册一个从GTypeInterface继承的不可实例的类型。下面的代码声明了这样的一个接口:
#define MAMAN_IBAZ_TYPE (maman_ibaz_get_type ()) #define MAMAN_IBAZ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_IBAZ_TYPE, MamanIbaz)) #define MAMAN_IS_IBAZ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_IBAZ_TYPE)) #define MAMAN_IBAZ_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MAMAN_IBAZ_TYPE, MamanIbazInterface)) typedef struct _MamanIbaz MamanIbaz; /* dummy object */ typedef struct _MamanIbazInterface MamanIbazInterface; struct _MamanIbazInterface { GTypeInterface parent; void (*do_action) (MamanIbaz *self); }; GType maman_ibaz_get_type (void); void maman_ibaz_do_action (MamanIbaz *self);
这里用非常简单的方法来实现maman_ibaz_do_action这个接口函数:
void maman_ibaz_do_action (MamanIbaz *self) { MAMAN_IBAZ_GET_INTERFACE (self)->do_action (self); }
maman_ibaz_get_type注册了一个从G_TYPE_INTERFACE继承的名为MamanIBaz的类型。在继承树中,所有的接口必须是G_TYPE_INTERFACE的子类。
一个接口只有一个包含GTypeInterface的结构来定义。接口的结构应该要包含一个函数指针指向这个接口的方法。用类似于maman_ibaz_do_action的方法在每个接口方法中定义帮助函数,可以使得我们直接调用接口方法,这是一个良好的风格。
一旦一个接口的类型被注册后,你必须来实现这个接口。其中,命名为maman_baz_get_type注册一个名为MamanBaz的由GObject继承来的新的GType,并在接口Interface中实现。
static void maman_baz_do_action (MamanIbaz *self) { g_print ("Baz implementation of IBaz interface Action./n"); } static void baz_interface_init (gpointer g_iface, gpointer iface_data) { MamanIbazInterface *iface = (MamanIbazInterface *)g_iface; iface->do_action = maman_baz_do_action; } GType maman_baz_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (MamanBazInterface), NULL, /* base_init */ NULL, /* base_finalize */ NULL, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ sizeof (MamanBaz), 0, /* n_preallocs */ NULL /* instance_init */ }; static const GInterfaceInfo ibaz_info = { (GInterfaceInitFunc) baz_interface_init, /* interface_init */ NULL, /* interface_finalize */ NULL /* interface_data */ }; type = g_type_register_static (G_TYPE_OBJECT, "MamanBazType", &info, 0); g_type_add_interface_static (type, MAMAN_IBAZ_TYPE, &ibaz_info); } return type; }
g_type_add_interface_static记录了在类型系统中如FooInterface来实现的接口(foo_interface_get_type返回FooInterface的类型),GInterfaceInfo保存着关于接口实现的信息:
struct _GInterfaceInfo { GInterfaceInitFunc interface_init; GInterfaceFinalizeFunc interface_finalize; gpointer interface_data; };
接口初始化
当一个对象的第一次注册一个接口实现时, 它的类结构由下述的方法所初始化。等类结构初始化后,函数type_class_init_Wm(实现在gtype.c)会初始化由类关联的每个接口,以type_iface_vtable_init_Wm调用每个接口。首先为接口结构分配内存缓冲,父接口结构先被复制(父接口先被初始化)。如果没有父接口,接口结构将由0初始化。g_type和g_instance_type将在其后被初始化:g_type被设置为最先起源的接口,g_instance_type被设置为最先起源的实现这个接口的类。
最终,接口的最顶层的base_init函数和实现接口的interface_init被调用。了解下面是重要的:如果有一个接口有多个base_init和interface_init的实现,那么每个实现都被调用一次以初始化。
base_init函数保持了一个本地静态变量用来确保这个接口类型只被初始化一次而不管它是否被实现了几次:
static void maman_ibaz_base_init (gpointer g_iface) { static gboolean initialized = FALSE; if (!initialized) { /* create interface signals here. */ initialized = TRUE; } }
如果你发现接口很烦,确实如此。它确实很烦,但是我也没办法啊。我只有把接口的过程归纳一下了!
Invocation time | Function Invoked | Function’s parameters | Remark |
---|---|---|---|
First call to g_type_create_instancefor type implementing interface | interface’ base_init function | On interface’ vtable | Register interface’ signals here (use a local static boolean variable as described above to make sure not to register them twice.). |
interface’ interface_init function | On interface’ vtable | Initialize interface’ implementation. That is, initialize the interface method pointers in the interface structure to the function’s implementation. |
接口的销毁
当最后一个实现某接口的实例被销毁以后,这个与类型相关联的接口实现也将由type_iface_vtable_finalize_Wm来销毁(gtype.c)type_iface_vtable_finalize_Wm调用了第一个实现的interface_finalize函数,接着是接口最底层的base_finalize函数。
同样,下面的理解非常重要,如“接口的初始化”中描述的,interface_finalize和base_finalize都将被调用来确保一个接口的实现被正确的销毁。例如,如果你曾用过其中一个函数,你将需要使用一个静态的整形来保持有关实例实现的接口的数量,这样接口的类才会只被销毁一次(当整型变量为0时)。
上面的处理过程总结如下:
Invocation time | Function Invoked | Function’s parameters |
---|---|---|
Last call to g_type_free_instancefor type implementing interface | interface’ interface_finalize function | On interface’ vtable |
interface’ base_finalize function | On interface’ vtable |
相关文章推荐
- GObject参考手册(5)--不可实例和不可类化的类型:基础类型
- GObject 参考手册:教程:如何定义和实现接口
- nginx全局变量实例对照 rewrite参考手册
- Linux 实例参考手册
- TypeScript手册1 - 基本类型和接口
- PHP - Manual手册 - Function Reference函数参考 - Variable and Type Related Extensions变量和类型相关扩展 - Arrays数组 - Array Functions数组函数 - ksort
- GObject 参考手册(12)--信号
- Maven:完整参考手册--1.3 一个通用的接口
- python3实例手册-基本类型-字符串
- Google地图接口API之Google地图 API 参考手册(七)
- libevent参考手册:辅助类型和函数(五)
- (大数据工程师学习路径)第五步 MySQL参考手册中文版----MySQL数据类型
- python-24-如何派生类内置不可变类型并修改其实例化行为?如何为创建大量实例节省内存?
- GObject参考手册(8)--基类:GObject
- 《PL/SQL 语言开发参考手册》之三:变量与数据类型
- MySQL 4.1.0 中文参考手册 --- 6.2 列类型
- GObject参考手册(1)--序
- libevent参考手册第五章:辅助类型和函数
- 简单工厂(Factory)-提供一个创建对象实例的功能,而无须关心其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。
- 《PL/SQL 语言开发参考手册》之三:变量与数据类型