GObject参考手册(10)--GObject的对象属性
来源:互联网 发布:淘宝客模式加活动 编辑:程序博客网 时间:2024/06/06 00:01
原文:http://library.gnome.org/devel/gobject/2.14/gobject-properties.html
GObject的其中一个漂亮特性就是它那为对象属性准备的通用get/set机制。当一个对象被实例化以后,对象的类初始化处理将用g_object_class_install_property来注册对象的属性(由gobject.c中实现)。
理解对象属性是如何工作的最好就是看下面的例子:
/************************************************//* Implementation *//************************************************/enum { MAMAN_BAR_CONSTRUCT_NAME = 1, MAMAN_BAR_PAPA_NUMBER,};static voidmaman_bar_instance_init (GTypeInstance *instance, gpointer g_class){ MamanBar *self = (MamanBar *)instance;}static voidmaman_bar_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec){ MamanBar *self = (MamanBar *) object; switch (property_id) { case MAMAN_BAR_CONSTRUCT_NAME: { g_free (self->priv->name); self->priv->name = g_value_dup_string (value); g_print ("maman: %s/n",self->priv->name); } break; case MAMAN_BAR_PAPA_NUMBER: { self->priv->papa_number = g_value_get_uchar (value); g_print ("papa: %u/n",self->priv->papa_number); } break; default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec); break; }}static voidmaman_bar_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec){ MamanBar *self = (MamanBar *) object; switch (property_id) { case MAMAN_BAR_CONSTRUCT_NAME: { g_value_set_string (value, self->priv->name); } break; case MAMAN_BAR_PAPA_NUMBER: { g_value_set_uchar (value, self->priv->papa_number); } break; default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec); break; }}static voidmaman_bar_class_init (gpointer g_class, gpointer g_class_data){ GObjectClass *gobject_class = G_OBJECT_CLASS (g_class); MamanBarClass *klass = MAMAN_BAR_CLASS (g_class); GParamSpec *pspec; gobject_class->set_property = maman_bar_set_property; gobject_class->get_property = maman_bar_get_property; pspec = g_param_spec_string ("maman-name", "Maman construct prop", "Set maman's name", "no-name-set" /* default value */, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); g_object_class_install_property (gobject_class, MAMAN_BAR_CONSTRUCT_NAME, pspec); pspec = g_param_spec_uchar ("papa-number", "Number of current Papa", "Set/Get papa's number", 0 /* minimum value */, 10 /* maximum value */, 2 /* default value */, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, MAMAN_BAR_PAPA_NUMBER, pspec);}/************************************************//* Use *//************************************************/GObject *bar;GValue val = {0,};bar = g_object_new (MAMAN_TYPE_SUBBAR, NULL);g_value_init (&val, G_TYPE_CHAR);g_value_set_char (&val, 11);g_object_set_property (G_OBJECT (bar), "papa-number", &val);
上面的例子看起来应该是简单的,但是很多事情发生了:
g_object_set_property先确保相应名称的属性已经在bar的class_init处理函数中被注册。如果是的话,它依次调用类继承关系中的object_set_property,从底至顶,基础类型用来找到注册了这个属性的类。接着它尝试转换用户提供的GValue到属性所关联的GValue。
如果用户提供了一个有符号的字符GValue,就像这里所示,如果对象的属性被注册为一个无符号的整型,g_value_transform将会试着转换输入的有符号的字符到一个无符号的整型。当然,转换是否成功取取决于可用的转换函数。实际上,如果需要的时候,总会有相关的转换函数可以用。
在转型以后,GValue将被g_param_value_validata来验证,以确保用户保存在GValue中的数据吻合由属性的GParamSpea所描述的字符特性。在这里,我们在class_init里提供的GParamSpec有一个验证函数来确保GValue包含了一个代表最小和最大边界的GParamSpec。在上面的例子中,客户端的GValue并没有尊重规范(它设置为了11,而最大值是10)。因为这样,所了g_object_set_property函数将返回一个错误。
如果用户的GValue已经被设置成了一个可用的值,g_object_set_property将处理一下呼叫至对象的set_property的类方法。在这里,因为我们在Foo的实现代码中并没有重载这个函数,代码路径将会跳到foo_set_property在收到g_object_class_install_property存储了GParamSpec的param_id后。
一时已经用对象的set_property类方法来设置好属性以后,代码路径将调用g_object_nofity_queue_thaw使返回到g_object_set_property 。这个函数确保“notify”信号”已经在对象实例完成改变属性后被发出,除非通知台已经被g_object_free_notify所冻洁。
g_object_thaw_nofity可以被用来重新启用通过“notify”信号的属性修改的通知中心。这是非常重要的,记住当属性被改变时通知中心是否被冻结,“notify”信号将会当在属性改变的一睡意由通知中心所发出:没有属性改变会因“notify”所信号。只有通过通知中心的冻结机制才能使信号发身被延误。
这听起来像是一个无聊的任务每次设置GValues当我想需要一个属性时。实际上我们仅仅很少这样做。g_object_set_property和g_object_get_property一般是用来语言绑定的。对应用程序来说,有一个更简单的方法,在下面描述。
同时修改多个属性
我想这很有趣,我们可以通过g_object_set和g_object_set_valist函数来同时设置多个属性值。客户端代码可以被重写为:
MamanBar *foo;foo = /* */;g_object_set (G_OBJECT (foo), "papa-number", 2, "maman-name", "test", NULL);
这个节省了我们管理用g_object_set_property来处理GValue的时间。在被修改时这个代码同样会触发每个属性。
当然,_get的版本同样是存在的:g_object_get和g_object-get_valist可以用来一次性得到很多属性。
这些高级的方法有一个缺点──它们不提供一个返回值。在使用它们时,你需要注意这些参数类型和范围 。(暂时不会了)
These high level functions have one drawback - they don’t provide a return result. One should pay attention to the argument types and ranges when using them. A know source of errors is to e.g. pass a gfloat instead of a gdouble and thus shifting all subsequent parameters by four bytes. Also forgetting the terminating NULL will lead to unexpected behaviour.
如果你认真看这章的话,现在你应该已经知道了g_object_new,g_object_newv和g_object_new_valist是如何工作的:它们解析用户提供的变量数目和参数并当对象成功的创建以后,用这些参数调用g_object_set。当然,“notify”信号同样会在每个属性改变后发射。
- GObject参考手册(10)--GObject的对象属性
- GObject参考手册(2)--概念:GObject的开发背景
- GObject参考手册(9)--GObject的内存管理
- GObject参考手册(8)--基类:GObject
- GObject的对象属性
- GObject参考手册(11)--GObject消息系统:Closure
- GObject参考手册(6)--可实例化的类型:对象
- GObject参考手册(4)--GLib的一些规范
- GObject参考手册(7)--不可实例的类型:接口
- GObject参考手册(1)--序
- GObject 参考手册(12)--信号
- GObject 子类对象的私有属性模拟
- GObject 子类对象的私有属性模拟
- GObject参考手册(3)--GLib动态类型系统
- GObject参考手册(5)--不可实例和不可类化的类型:基础类型
- GObject
- GObject
- gobject
- 高性能Web Service数据库编程
- NHiberante源码分析之: 事务
- 装了VS2008
- Using OLE DB Consumer Templates
- NHibernate2.0之旅系列文章导航
- GObject参考手册(10)--GObject的对象属性
- IDispatch接口原理与应用
- 解决struts2的数据校验会促使action与框架耦合问题
- SQL与oracle分页存储过程
- ADO编程实用宝典
- ADO编程总结
- 系统程序员成长计划-写得又快又好的秘诀
- GObject参考手册(11)--GObject消息系统:Closure
- SAFEARRAY使用实例