Справочное описание GObject |
---|
Для определения что интерфейс требует присутствия других интерфейсов при реализации, GObject вводит понятие предпосылки: возможность связать список необходимых как условие интерфейсов с интерфейсом. Например, если объект A хочет реализовать интерфейс I1, и если интерфейс I1 имеет предпосылку на интерфейс I2, A реализует оба интерфейса I1 и I2.
Механизм описанный выше на практике очень похож на Java, интерфейс I1 дополняется интерфейсом I2. Пример ниже показывает GObject эквивалент:
type = g_type_register_static (G_TYPE_INTERFACE, "MamanIbar", &info, 0);
/* Создаём интерфейс MamanIbar требующий интерфейс MamanIbaz. */
g_type_interface_add_prerequisite (type, MAMAN_TYPE_IBAZ);
Код показанный выше добавляет интерфейс MamanIbaz в список предпосылок MamanIbar в то время как код ниже показывает как реализовать оба интерфейса и зарегистрировать их реализацию:
static void ibar_do_another_action (MamanBar *self)
{
g_print ("Bar implementation of IBar interface Another Action: 0x%x.\n", self->instance_member);
}
static void
ibar_interface_init (gpointer g_iface,
gpointer iface_data)
{
MamanIbarInterface *iface = (MamanIbarInterface *)g_iface;
iface->do_another_action = (void (*) (MamanIbar *self))ibar_do_another_action;
}
static void ibaz_do_action (MamanBar *self)
{
g_print ("Bar implementation of IBaz interface Action: 0x%x.\n", self->instance_member);
}
static void
ibaz_interface_init (gpointer g_iface,
gpointer iface_data)
{
MamanIbazInterface *iface = (MamanIbazInterface *)g_iface;
iface->do_action = (void (*) (MamanIbaz *self))ibaz_do_action;
}
static void
bar_instance_init (GTypeInstance *instance,
gpointer g_class)
{
MamanBar *self = (MamanBar *)instance;
self->instance_member = 0x666;
}
GType
maman_bar_get_type (void)
{
static GType type = 0;
if (type == 0) {
static const GTypeInfo info = {
sizeof (MamanBarClass),
NULL, /* base_init */
NULL, /* base_finalize */
NULL, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (MamanBar),
0, /* n_preallocs */
bar_instance_init /* instance_init */
};
static const GInterfaceInfo ibar_info = {
(GInterfaceInitFunc) ibar_interface_init, /* interface_init */
NULL, /* interface_finalize */
NULL /* interface_data */
};
static const GInterfaceInfo ibaz_info = {
(GInterfaceInitFunc) ibaz_interface_init, /* interface_init */
NULL, /* interface_finalize */
NULL /* interface_data */
};
type = g_type_register_static (G_TYPE_OBJECT,
"MamanBarType",
&info, 0);
g_type_add_interface_static (type,
MAMAN_TYPE_IBAZ,
&ibaz_info);
g_type_add_interface_static (type,
MAMAN_TYPE_IBAR,
&ibar_info);
}
return type;
}
Важно обратить внимание что порядок, в котором реализованные интерфейсы добавляются к основному объекту, не случаен:
g_type_add_interface_static
должна быть вызвана сначала для интерфейсов которые не имеют никаких предпосылок а зтем для остальных.
Полный исходный код, показывающий как определить интерфейс MamanIbar который требует MamanIbaz и как реализовать
интерфейс MamanIbar, расположен в sample/interface/maman-ibar.{h|c}
и sample/interface/maman-bar.{h|c}
.