Предпосылки определения Интерфейса

Для определения что интерфейс требует присутствия других интерфейсов при реализации, 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}.