您的位置:首页 > 移动开发 > Objective-C

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继承的不可实例的类型。下面的代码声明了这样的一个接口:
#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 timeFunction InvokedFunction’s parametersRemark
First call to
g_type_create_instance
for type implementing interface
interface’ base_init functionOn interface’ vtableRegister interface’ signals here (use a local static boolean variable as described above to make sure not to register them twice.).
interface’ interface_init functionOn interface’ vtableInitialize 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 timeFunction InvokedFunction’s parameters
Last call to
g_type_free_instance
for type implementing interface
interface’ interface_finalize functionOn interface’ vtable
interface’ base_finalize functionOn interface’ vtable
你已经读完了这章,现在你可以忘记它了。请尽可能快地忘记它!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: