GTK接口定义和实现

一、接口定义

GObject接口如何工作的理论在“非实例化类类型:接口”一节中给出。 本节介绍如何定义和实现一个接口。
第一步是取一个正确的名称。 该接口定义了两种方法:

 

/*
 * Copyright/Licensing information.
 */

#ifndef __VIEWER_EDITABLE_H__
#define __VIEWER_EDITABLE_H__

#include <glib-object.h>

G_BEGIN_DECLS

#define VIEWER_TYPE_EDITABLE viewer_editable_get_type ()
G_DECLARE_INTERFACE (ViewerEditable, viewer_editable, VIEWER, EDITABLE, GObject)

struct _ViewerEditableInterface
{
  GTypeInterface parent_iface;

  void (*save) (ViewerEditable  *self,
                GError         **error);
  void (*undo) (ViewerEditable  *self,
                guint            n_steps);
  void (*redo) (ViewerEditable  *self,
                guint            n_steps);
};

void viewer_editable_save (ViewerEditable  *self,
                           GError         **error);
void viewer_editable_undo (ViewerEditable  *self,
                           guint            n_steps);
void viewer_editable_redo (ViewerEditable  *self,
                           guint            n_steps);

G_END_DECLS

#endif /* __VIEWER_EDITABLE_H__ */

该代码与继承自GObject的普通GType的代码相同,除了几个细节:
1、_GET_CLASS函数称为_GET_IFACE(由G_DECLARE_INTERFACE定义)。

 

2、实例类型ViewerEditable没有被完全定义:它仅被用作一个抽象类型,它表示实现该接口的任何对象的一个​​实例。
3、ViewerEditableInterface的父级是GTypeInterface,而不是GObjectClass。
ViewerEditable类型本身的实现是微不足道的:

1、G_DEFINE_INTERFACE创建一个viewer_editable_get_type函数,该函数在类型系统中注册类型。第三个参数用于定义一个先决条件接口(稍后我们再讨论一下)。当接口没有先决条件时,只需为此参数传递0。
2、viewer_editable_default_init预计会注册接口的信号,如果有的话(稍后会看到如何使用它们)。

3、接口方法viewer_editable_save,viewer_editable_undo和viewer_editable_redo取消引用接口结构以访问其关联的接口函数并调用它。

G_DEFINE_INTERFACE (ViewerEditable, viewer_editable, G_TYPE_OBJECT);

static void
viewer_editable_default_init (ViewerEditableInterface *iface)
{
    /* add properties and signals to the interface here */
}

void
viewer_editable_save (ViewerEditable  *self,
                      GError         **error)
{
  ViewerEditableInterface *iface;

  g_return_if_fail (VIEWER_IS_EDITABLE (self));
  g_return_if_fail (error == NULL || *error == NULL);

  iface = VIEWER_EDITABLE_GET_IFACE (self);
  g_return_if_fail (iface->save != NULL);
  iface->save (self, error);
}

void
viewer_editable_undo (ViewerEditable *self,
                      guint           n_steps)
{
  ViewerEditableInterface *iface;

  g_return_if_fail (VIEWER_IS_EDITABLE (self));

  iface = VIEWER_EDITABLE_GET_IFACE (self);
  g_return_if_fail (iface->undo != NULL);
  iface->undo (self, n_steps);
}

void
viewer_editable_redo (ViewerEditable *self,
                      guint           n_steps)
{
  ViewerEditableInterface *iface;

  g_return_if_fail (VIEWER_IS_EDITABLE (self));

  iface = VIEWER_EDITABLE_GET_IFACE (self);
  g_return_if_fail (iface->redo != NULL);
  iface->redo (self, n_steps);
}

二、实现

一旦界面被定义,实现它是相当微不足道的。
第一步是定义一个正常的最终GObject类,正如在“Boilerplate标题代码”一节中所述。
第二步是通过使用G_DEFINE_TYPE_WITH_CODE和G_IMPLEMENT_INTERFACE而不是G_DEFINE_TYPE定义来实现ViewerFile:

static void viewer_file_editable_interface_init (ViewerEditableInterface *iface);

G_DEFINE_TYPE_WITH_CODE (ViewerFile, viewer_file, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE,
                                                viewer_file_editable_interface_init))

类可以通过在对G_DEFINE_TYPE_WITH_CODE的调用中使用多次调用G_IMPLEMENT_INTERFACE来实现多个接口。
viewer_file_editable_interface_init,接口初始化函数:它里面的接口的每个虚拟方法必须分配给它的实现

static void
viewer_file_editable_save (ViewerFile  *self,
                           GError     **error)
{
  g_print ("File implementation of editable interface save method: %s.\n",
           self->filename);
}

static void
viewer_file_editable_undo (ViewerFile *self,
                           guint       n_steps)
{
  g_print ("File implementation of editable interface undo method: %s.\n",
           self->filename);
}

static void
viewer_file_editable_redo (ViewerFile *self,
                           guint       n_steps)
{
  g_print ("File implementation of editable interface redo method: %s.\n",
           self->filename);
}

static void
viewer_file_editable_interface_init (ViewerEditableInterface *iface)
{
  iface->save = viewer_file_editable_save;
  iface->undo = viewer_file_editable_undo;
  iface->redo = viewer_file_editable_redo;
}

static void
viewer_file_init (ViewerFile *self)
{
  /* Instance variable initialisation code. */
}


 

posted @ 2017-05-02 16:07  luizp  阅读(309)  评论(0编辑  收藏  举报