Свойства интерфейса

Начиная с версии glib 2.4, GObject интерфейсы могут также иметь свойства. Декларация свойств интерфейса похожа на декларацию свойств обычных типов GObject как показано в “Object properties”, исключая то, что g_object_interface_install_property используется для декларации свойств вместо g_object_class_install_property.

Для включения свойства с именем 'name' типа string в код выше приведённого примера интерфейса maman_ibaz, нам нужно добавить только одну[14] строчку в maman_ibaz_base_init[15] как показано ниже:

static void maman_ibaz_base_init (gpointer g_iface) { static gboolean initialized = FALSE; if (!initialized) { /* здесь создаём сигналы интерфейса. */ g_object_interface_install_property (g_iface, g_param_spec_string ("name", "maman_ibaz_name", "Name of the MamanIbaz", "maman", G_PARAM_READWRITE)); initialized = TRUE; } }

Одно замечание - задекларированному свойству не был присвоен целочисленный ID. Причина в том, что целочисленный ID этого свойства используется только внутри методов получения и установки, а так как интерфейс не реализует свойства, нет необходимости привязывать целочисленный ID к свойствам интерфейса.

История для конструкторов интерфейса также весьма тривиальна. Конструктор должен задекларировать и определить свойства обычным способом как описано в the section called “Object properties”, за исключением одной мелочи: он должен задекларировать свойства интерфейса используя g_object_class_override_property вместо g_object_class_install_property. Следующий код демонстрирует изменения необходимые в декларации и реализации MamanBaz показанной выше:

struct _MamanBaz { GObject parent; gint instance_member; gchar *name; /* метка для свойства */ }; enum { ARG_0, ARG_NAME }; GType maman_baz_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (MamanBazClass), NULL, /* base_init */ NULL, /* base_finalize */ baz_class_init, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ sizeof (MamanBaz), 0, /* n_preallocs */ baz_instance_init /* 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_TYPE_IBAZ, &ibaz_info); } return type; } static void maman_baz_class_init (MamanBazClass * klass) { GObjectClass *gobject_class; gobject_class = (GObjectClass *) klass; parent_class = g_type_class_ref (G_TYPE_OBJECT); gobject_class->set_property = maman_baz_set_property; gobject_class->get_property = maman_baz_get_property; g_object_class_override_property (gobject_class, ARG_NAME, "name"); } static void maman_baz_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { MamanBaz *baz; GObject *obj; /* it's not null if we got it, but it might not be ours */ g_return_if_fail (G_IS_MAMAN_BAZ (object)); baz = MAMAN_BAZ (object); switch (prop_id) { case ARG_NAME: baz->name = g_value_get_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void maman_baz_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { MamanBaz *baz; /* it's not null if we got it, but it might not be ours */ g_return_if_fail (G_IS_TEXT_PLUGIN (object)); baz = MAMAN_BAZ (object); switch (prop_id) { case ARG_NAME: g_value_set_string (value, baz->name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }



[14] Это действительно одна строка расширенная на шесть для ясности

[15] g_object_interface_install_property может также быть вызвана из class_init но её нельзя вызвать после этой точки.