GObject学习(三)

本文介绍了如何在GObject子类中安全地访问私有属性,强调了使用get和set方法的重要性,以避免数据变化对程序功能的影响。通过示例,展示了如何实现g_object_new函数的参数用于初始化对象属性,并详细讲解了属性的安装和使用过程,包括set_property和get_property函数的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文是笔者整理网上资料加上一些自己实践的纪录,本文的主体内容转自如下文章:

源博客网址:http://garfileo.is-programmer.com/categories/6934/posts

以下是本文的所主要学习实践的其中d这个小题目的原文链接。
http://garfileo.is-programmer.com/2011/3/4/accessing-properties-of-gobject-subclass.24952.html#ref-3

该文没有其他好特别说的,主要学习的是对私有数据的“好”的访问方法及其必要性。其实就是get和set方法。只不过Gobject的get和set方法有一定的步骤。
唯一需要特别关注的是,属性的安装是在class_init中完成的。

以下是作者原文转载,放在此处纯属为了自己方便,并防止原文地址丢失。


GObject 子类私有属性的外部访问

之前,写了一篇 GObject 劝学的文章 [1],还有两篇有关 GObject 子类对象数据封装的文章 [2, 3]。

虽然,创建一个 GObject 子类对象需要一些辅助函数和宏的支持,并且它们的内幕也令人费解,但是只要将足够的信任交托给 GObject 开发者,将那些辅助函数和宏当作“语法”糖一样享用,一切还是挺简单的。至于细节,还是等较为全面的掌握 GObject 库的用法之后再去挖掘!

现在,我们基本上知道了如何将数据封装并藏匿于 GObject 子类的实例结构体中。本文打算再向前走一步,关注如何实现在外部比较安全的访问(读写)这些数据。
简单的做法

像下面这样的双向链表数据结构:

typedef struct _PMDListNode PMDListNode;
struct _PMDListNode {
   
        PMDListNode *prev;
        PMDListNode *next;
};
 
typedef struct _PMDList PMDList;
struct _PMDList {
   
        PMDListNode *head;
        PMDListNode *tail;
};

现在,我们希望能够安全访问 PMDList 结构题的两个成员,即链表的首结点指针 head 和尾结点指针 tail,以便进行一些操作,例如将两个双向链表 list1 和 list2 链接到一起。

所谓安全访问,意味着不要像下面这样简单粗暴:

/* 将 list1 与 list2 链接在一起 */
list1->tail->next = list2->head;
list2->head->prev = list1->tail;

而应当委婉一些:

PMDListNode *list1_tail, *list2_head;
 
list1_tail = pm_dlist_get (list1, TAIL);
list2_head = pm_dlist_get (list2, HEAD);
 
pm_dlist_set (list1, TAIL, NEXT, list2_head);
pm_dlist_set (list2, HEAD, PREV, list1_tail);

这样委婉的访问,有什么好处?答案很简单,可以将数据的变化与程序的功能隔离开,数据的变化不影响程序的功能。

试想,如果有一天,上述 PMDList 结构体的设计者使用 GObject 子类化的方法将双向链表定义为建 PMDList 类的形式,并且将链表的首结点指针 head 与尾结点都隐匿起来,那么上述的那个简单粗暴的数据访问方法便失效了。更糟糕的是,PMDList 类的设计者明知道很多人会受到这种数据变化的影响,对此也毫无办法。

如果 PMDList 结构体的设计者提供了 pm_dlist_set 与 pm_dlist_get 函数,那么即便设计者基于 GObject 子类化的方式定义了 PMDList 类,他只需要修改 pm_dlist_set 和 pm_dlist_get 函数,便可以让上述那种委婉方式访问 PMDList 结构体成员的代码不会受到任何影响。

既然 pm_dlist_set 与 pm_dlist_get 函数这样有用,我们可以像下面这样实现它们。

typedef enum _PM_DLIST_PROPERTY PM_DLIST_PROPERTY
enum _PM_DLIST_PROPERTY {
   
        PM_DLIST_HEAD,
        PM_DLIST_TAIL,
        PM_DLIST_NODE_PREV,
        PM_DLIST_NODE_NEXT
};
 
PMDListNode *
pm_dlist_get (PMDList *self, PM_DLIST_PROPERTY property)
{
   
        PMDListNode *node = NULL;
 
        switch (property) {
   
        case PM_DLIST_HEAD:
                node = self->head;
                break;
        case PM_DLIST_TAIL:
                node = self->tail;
                break;
        default:
                g_print ("对不起,你访问的成员不存在!\n");
        }
 
        return node;
}
 
void
pm_dlist_set (PMDList *self, 
              PM_DLIST_PROPERTY property,
              PM_DLIST_PROPERTY subproperty,
              PMDListNode *node)
{
   
        switch (property) {
   
        case PM_DLIST_HEAD:
                if (subproperty == PM_DLIST_NODE_PREV)
                        self->head->prev = node;
                else if (subproperty == PM_DLIST_NODE_NEXT)
                        self->head->next = node;
                break;
        case PM_DLIST_TAIL:
                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值