Свойства объекта
Last updated
Was this helpful?
Last updated
Was this helpful?
Одной из замечательных особенностей GObject является родной механизм установки/получения свойств для объекта. Когда объект инстанциирован, объектный обработчик class_init должен использоваться для регистрации свойств объекта с помощью (реализована в gobject.c
).
Лучший способ понять как работают свойства объекта - посмотреть реальный пример их использования:
Код клиента продемонстрированный выше прост, но большинство вещей происходит скоытно:
Эти функции высокого уровня имеют один недостаток - они не обеспечивают возвращаемый результат. Нужно обращать внимание на типы аргументов и диапазон их использования. Известный источник ошибок например помещение gfloat вместо gdouble и таким образом смещение всех последующих параметров на четыре байта. Также отсутствие завершающего NULL может привести к неожиданному поведению.
убеждается что свойство с таким названием было зарегистрировано обработчиком class_init в данной области. Если это так, она вызывает object_set_property
которая обходит иерархию класса, от основания большинства производных типов, до вершины базового типа в поиске класса который зарегистрировал это свойство. Затем она пытается конвертировать обеспеченную пользователем GValue в GValue чей тип связан с этим свойством.
Если пользователь обеспечил signed char GValue, как показано здесь, и если свойство объекта было зарегистрировано как unsigned int, попытается преобразовать введённый signed char в unsigned int. Конечно успех преобразования зависит от возможностей преобразующей функции. На практике, почти всегда будет соответствующее преобразование [] и преобразование будет перенесено если необходимо.
После преобразования, утверждается с помощью которая проверяет чтобы пользовательские данные сохранённые в соответствовали характеристикам определённым свойства. Здесь, мы обеспечили в функции class_init имеющей функцию проверки допустимости значений содержащихся в GValue, которые придерживаются минимальных и максимальных границ . В примере выше, GValue клиента не придерживается этих ограничений (оно установлено в 11, тогда как максимум равен 10). Поэтому функция вернёт ошибку.
Если пользовательское GValue установлено в допустимое значение, продолжит процесс вызова объектного метода класса set_property. В примере, так как наша реализация Foo отменяла этот метод, код перейдёт в foo_set_property
найдя с param_id [] который был сохранён с помощью .
Как только свойство было установлено объектным методом класса set_property, код возвращается в которая вызывает g_object_notify_queue_thaw
. Эта функция убеждается что сигнал "notify" произошёл в экземпляре объекта с изменённым свойством в качестве параметра, если уведомления не были заморожены .
может использоваться для нового уведомления изменения свойства через сигнал "notify". Важно помнить что даже если свойства изменены в то время как уведомление изменения свойств заморожено, сигнал "notify" издаётся один раз для каждого из изменённых свойств, как только уведомление изменения свойства разморожено: ни одно изменение свойства не теряется для сигнала "notify". Сигнал может быть отсрочен с помощью механизма заморозки уведомления.
Похоже на утомительную задачу устанавливать GValues каждый раз когда необходимо изменить свойство. На практике, очень редко придётся это делать. Функции и предназначены для использования языковыми привязками. Для приложений есть более простой способ и он описан далее.
Интересно отметить что и (vararg версия) могут использоваться для установки множества свойств одновременно. Код клиента показанный выше можно переписать как:
Это оберегает нас от управления GValues который мы должны были обработать используя . Код выше переключает одну эмиссию сигнала уведомления для каждого изменяемого свойства.
Конечно, версия _get также доступна: и (vararg версия) могут использоваться для получения множества свойств сразу.
Внимательные читатели теперь понимают как работают , и : они анализируют количество пользовательских переменных и вызывают для параметров только после полного проектирования объекта. Естественно, сигнал "notify" издаётся для каждого установленного свойства.
[] Это может быть не то что вам нужно, но это позволяет вам решать полагаться ли на эти преобразования.
[] Должно быть отмечено, что используемый здесь param_id уникален для идентификации каждого внутри FooClass так что переключение используемое в методах установка и получение фактически работает. Конечно, эти локальные уникальные целочисленные - просто оптимизация: возможно было бы использовать набор условий if (strcmp (a, b) == 0) {} else if (strcmp (a, b) == 0) {}.