四、GObject子类的继承

1 Bibtex文献类的设计

1.1 Bibtex类头文件

/* file name: my-bibtex.h */
#ifndef KB_BIBTEX_H
#define KB_BIBTEX_H

#include<glib-object.h>

#define MY_TYPE_BIBTEX (my_bibtex_get_type())
#define MY_BIBTEX(object) \
        G_TYPE_CHECK_INSTANCE_CAST ((object), MY_TYPE_BIBTEX, MyBibtex)

typedef struct _MyBibtex MyBibtex;
struct _MyBibtex{
  GObject parent;
};

typedef struct _MyBibtexClass MyBibtexClass;
struct _MyBibtexClass{
  GObjectClass parent_class;
};

GType my_bibtex_get_type(void);

void 
my_bibtex_printf(MyBibtex *self);

#endif

1.2 Bibtex类函数实现

#include"my-bibtex.h"

/* 类型注册 系统自动生成my_bibtex_get_type()函数 */
G_DEFINE_TYPE (MyBibtex, my_bibtex, G_TYPE_OBJECT);

#define MY_BIBTEX_GET_PRIVATE(object) (\
        G_TYPE_INSTANCE_GET_PRIVATE ((object), MY_TYPE_BIBTEX, MyBibtexPrivate))

/* 对象私有属性 */
typedef struct _MyBibtexPrivate MyBibtexPrivate;
struct _MyBibtexPrivate{
  GString *title;
  GString *author;
  GString *publisher;
  guint year;
};

enum PROPERTY_BIBTEX {
  PROPERTY_0,
  PROPERTY_TITLE,
  PROPERTY_AUTHOR,
  PROPERTY_PUBLISHER,
  PROPERTY_YEAR,
  N_PROPERTIES
};

static void
my_bibtex_set_property (GObject *object, guint property_id,
                        const GValue *value, GParamSpec *pspec)
{       
  MyBibtex *self = MY_BIBTEX (object);
  MyBibtexPrivate *priv = MY_BIBTEX_GET_PRIVATE (self);
    
  switch (property_id) {
  case PROPERTY_TITLE:
        if (priv->title)
                g_string_free (priv->title, TRUE);
        priv->title = g_string_new (g_value_get_string (value));
        break;
  case PROPERTY_AUTHOR:
        if (priv->author)
                g_string_free (priv->author, TRUE);
        priv->author = g_string_new (g_value_get_string (value));
        break;
  case PROPERTY_PUBLISHER:
        if (priv->publisher)
                g_string_free (priv->publisher, TRUE);
        priv->publisher = g_string_new (g_value_get_string (value));
        break;
  case PROPERTY_YEAR:
        priv->year = g_value_get_uint (value);
        break;
  default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
        break;
  }
}
 
static void
my_bibtex_get_property (GObject *object, guint property_id,
                        GValue *value, GParamSpec *pspec)
{
  MyBibtex *self = MY_BIBTEX (object);
  MyBibtexPrivate *priv = MY_BIBTEX_GET_PRIVATE (self);
  GString *similar = NULL;
    
  switch (property_id) {
  case PROPERTY_TITLE:
        g_value_set_string (value, priv->title->str);
        break;
  case PROPERTY_AUTHOR:
        g_value_set_string (value, priv->author->str);
        break;
  case PROPERTY_PUBLISHER:
        g_value_set_string (value, priv->publisher->str);
        break;
  case PROPERTY_YEAR:
        g_value_set_uint (value, priv->year);
        break;
  default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
        break;
  }
}

/* 参数名之所以使用klass而不是class,为了C++编译的时候防止和关键字class冲突 */
static void
my_bibtex_class_init (MyBibtexClass *klass)
{
  g_type_class_add_private (klass, 
                            sizeof (MyBibtexPrivate));
  GObjectClass *base_class = G_OBJECT_CLASS (klass);
  base_class->set_property = my_bibtex_set_property;
  base_class->get_property = my_bibtex_get_property;
  GParamSpec *properties[N_PROPERTIES] = {NULL,};
  properties[PROPERTY_TITLE] =
          g_param_spec_string ("title",
                                "Title",
                                "Bibliography title",
                                NULL,
                                G_PARAM_READWRITE);
  properties[PROPERTY_AUTHOR] =
          g_param_spec_string ("author",
                                "Author",
                                "Bibliography author",
                                NULL,
                                G_PARAM_READWRITE);
  properties[PROPERTY_PUBLISHER] =
          g_param_spec_string ("publisher",
                                "Publisher",
                                "Bibliography Publisher",
                                NULL,
                                G_PARAM_READWRITE);
  properties[PROPERTY_YEAR] =
          g_param_spec_uint ("year",
                              "Year",
                              "Bibliography year",
                              0,
                              G_MAXUINT,
                              0,
                              G_PARAM_READWRITE);
  g_object_class_install_properties (base_class, N_PROPERTIES, properties);

}

static void
my_bibtex_init (MyBibtex *self)
{
}

void 
my_bibtex_printf(MyBibtex *self)
{
  gchar *title, *author, *publisher;
  gint year;

  g_object_get(G_OBJECT(self),
               "title", &title,
               "author", &author,
               "publisher", &publisher,
               "year", &year,
               NULL);

  g_printf("    Title: %s\n"
           "   Author: %s\n"
           "Publisher: %s\n"
           "     Year: %d\n", title, author, publisher, year);
  
  /*g_free 是因为系统重新创建了字符串内存空间,没有指向私有属性的地址*/
  g_free(title);
  g_free(author);
  g_free(publisher);
}

分析
  除了构造类属性,与前面的有所区别,本文采用的是ParamSpec类型的指针数组,一遍在类属性构造完毕后,使用个g_object_class_install_properties函数一并安装到类结构体中。 而不是像上一篇文档那样g_object_class_install_property一个一个安装。
  打印输出文献信息函数,为什么要释放内存。因为get_property属性的时候,新建的一个字符串变量。该变量不等于私有属性字符串变量地址。故必须释放,且不会引起私有属性错误。

2 Article文献类的设计

2.1 Article文献类头文件

#include"my-bibtex.h"

/* 类的数据类型获取函数宏 */
#define MY_TYPE_ARTICLE (my_article_get_type())

#define MY_ARTICLE(object) \
        G_TYPE_CHECK_INSTANCE_CAST ((object), MY_TYPE_ARTICLE, MyArticle)

typedef struct _MyArticle MyArticle;
struct _MyArticle{
  MyBibtex parent;
};

typedef struct _MyArticleClass MyArticleClass;
struct _MyArticleClass{
  MyBibtexClass parent_class;
};

GType
my_article_get_type();

void 
my_article_printf(MyArticle *self);

分析
  类实例结构体和类结构体都是继承与MyBibtex类。

2.2 Article类函数实现

#include"my-article.h"
#include"my-bibtex.h"

G_DEFINE_TYPE(MyArticle, my_article, MY_TYPE_BIBTEX);
#define MY_ARTICLE_GET_PRIVATE(object) (\
        G_TYPE_INSTANCE_GET_PRIVATE ((object), MY_TYPE_ARTICLE, MyArticlePrivate))


/* 对象私有属性 */
typedef struct _MyArticlePrivate MyArticlePrivate;
struct _MyArticlePrivate{
  GString *journal;
  GString *volume;
  GString *number;
  GString *pages;
};

enum PROPERTY_ARTICLE {
  PROPERTY_0,
  PROPERTY_JOURNAL,
  PROPERTY_VOLUME,
  PROPERTY_NUMBER,
  PROPERTY_PAGES,
  N_PROPERTIES
};

static void
my_article_set_property (GObject *object, guint property_id,
                        const GValue *value, GParamSpec *pspec)
{       
  MyArticle *self = MY_ARTICLE (object);
  MyArticlePrivate *priv = MY_ARTICLE_GET_PRIVATE (self);
    
  switch (property_id) {
  case PROPERTY_JOURNAL:
        if (priv->journal)
                g_string_free (priv->journal, TRUE);
        priv->journal = g_string_new (g_value_get_string (value));
        break;
  case PROPERTY_VOLUME:
        if (priv->volume)
                g_string_free (priv->volume, TRUE);
        priv->volume = g_string_new (g_value_get_string (value));
        break;
  case PROPERTY_NUMBER:
        if (priv->number)
                g_string_free (priv->number, TRUE);
        priv->number = g_string_new (g_value_get_string (value));
        break;
  case PROPERTY_PAGES:
        if (priv->pages)
                g_string_free (priv->pages, TRUE);
        priv->pages = g_string_new (g_value_get_string (value));
        break;
  default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
        break;
  }
}
 
static void
my_article_get_property (GObject *object, guint property_id,
                        GValue *value, GParamSpec *pspec)
{
  MyArticle *self = MY_ARTICLE (object);
  MyArticlePrivate *priv = MY_ARTICLE_GET_PRIVATE (self);
  GString *similar = NULL;
    
  switch (property_id) {
  case PROPERTY_JOURNAL:
        g_value_set_string (value, priv->journal->str);
        break;
  case PROPERTY_VOLUME:
        g_value_set_string (value, priv->volume->str);
        break;
  case PROPERTY_NUMBER:
        g_value_set_string (value, priv->number->str);
        break;
  case PROPERTY_PAGES:
        g_value_set_string (value, priv->pages->str);
        break;
  default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
        break;
  }
}

/* 参数名之所以使用klass而不是class,为了C++编译的时候防止和关键字class冲突 */
static void
my_article_class_init (MyArticleClass *klass)
{
  g_type_class_add_private (klass, 
                            sizeof (MyArticlePrivate));

  GObjectClass *base_class = G_OBJECT_CLASS (klass);
  g_printf("Article***: %p\n", base_class);
  base_class->set_property = my_article_set_property;
  base_class->get_property = my_article_get_property;
  GParamSpec *properties[N_PROPERTIES] = {NULL,};
  properties[PROPERTY_JOURNAL] =
          g_param_spec_string ("journal",
                                "Journal",
                                "Bibliography journal",
                                NULL,
                                G_PARAM_READWRITE);
  properties[PROPERTY_VOLUME] =
          g_param_spec_string ("volume",
                                "Volume",
                                "Bibliography volume",
                                NULL,
                                G_PARAM_READWRITE);
  properties[PROPERTY_NUMBER] =
          g_param_spec_string ("number",
                                "Number",
                                "Bibliography number",
                                NULL,
                                G_PARAM_READWRITE);
  properties[PROPERTY_PAGES] =
          g_param_spec_string ("pages",
                              "Pages",
                              "Bibliography pages",
                              NULL,
                              G_PARAM_READWRITE);
  g_object_class_install_properties (base_class, N_PROPERTIES, properties);
}

static void
my_article_init (MyArticle *self)
{
}


void 
my_article_printf(MyArticle *self)
{
  my_bibtex_printf(&self->parent);

  gchar *journal, *volume, *number, *pages;

  g_object_get(G_OBJECT(self),
               "journal", &journal,
               "volume", &volume,
               "number", &number,
               "pages", &pages,
               NULL);

  g_printf("  Journal: %s\n"
           "   Volume: %s\n"
           "   Number: %s\n"
           "    Pages: %s\n", journal, volume, number, pages);
  
  /*g_free 是因为系统重新创建了字符串内存空间,没有指向私有属性的地址*/
  g_free(journal);
  g_free(volume);
  g_free(number);
  g_free(pages);
}

分析
  G_DEFINE_TYPE(MyArticle, my_article, MY_TYPE_BIBTEX);
第三个参数是父类结构体信息。

3 主函数的实现

#include"my-bibtex.h"
#include"my-article.h"

int
main (void)
{
  g_type_init ();
    
  MyArticle *entry = g_object_new (MY_TYPE_ARTICLE,
                                    "title", "Breaking paragraphs into lines",
                                    "author", "Knuth, D.E. and Plass, M.F.",
                                    "publisher", "Wiley Online Library",
                                    "journal", "Software: Practice and Experience",
                                    "volume", "11",
                                    "number", "11",
                                    "year", 1981,
                                    "pages", "1119-1184",
                                    NULL);
  my_article_printf (entry);

  g_object_unref (entry);
  return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值