GTK 的物件导向架构

GTK 基本上是使用 C 语言来撰写,即使C语言本身不支援物件导向,但GTK在架构上运用了一些方式,使得使用GTK时可以支援许多物件导向的概念。

在物件导向的封装特性上,GTK以结构(structure)的方式来模拟类别,事实上GTK也直接称这些结构为类别,以建构GtkWindow的程式码为例:
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

在函式的组织上,与GtkWindow相关的函式,都是以gtk_window名称作为开头,gtk_window_new()就像是物件导向程式语言中的建构式,如果要设置GtkWindow的相关属性,例如标题名称:
gtk_window_set_title(GTK_WINDOW(window), "哈啰!GTK+!");

gtk_window_set_title()的第一个参数接受GtkWindow指标,透过这种方式,让实际上属于全域的函 式,看来就像是专属于GtkWindow所使用,就如同物件上所带有的公开(public)方法(method)或成员函式(member function),而在私有(private)的模拟上,GTK使用static函式,例如在gtkwindow.c原始程式码中,可以看到:
static void gtk_window_dispose            (GObject           *object);
static void gtk_window_destroy            (GtkObject         *object);
static void gtk_window_finalize           (GObject           *object);
static void gtk_window_show               (GtkWidget         *widget);
static void gtk_window_hide               (GtkWidget         *widget);
static void gtk_window_map                (GtkWidget         *widget);
static void gtk_window_unmap              (GtkWidget         *widget);
static void gtk_window_realize            (GtkWidget         *widget);
static void gtk_window_unrealize          (GtkWidget         *widget);

这些static函式不会出现在gtkwindow.h标头文件中,仅可在gtkwindow.c中使用,这看起来就像是GtkWindow的专属私用函式。

在继承上,GTK实际上使用结构链接(link)的方式,在
第一个 GTK 程式 中看过以下的继承关系:
GObject
 +--GInitiallyUnowned
     +-- GtkObject
           +-- GtkWidget
                 +-- GtkContainer
                       +-- GtkBin
                             +-- GtkWindow

以GtkContainer为例,在gtkcontainer.h中有如下的定义:
typedef struct _GtkContainer       GtkContainer;
...

struct _GtkContainer
{
  GtkWidget widget;
 
  GtkWidget *focus_child;
 
  guint border_width : 16;

  /*< private >*/
  guint need_resize : 1;
  guint resize_mode : 2;
  guint reallocate_redraws : 1;
  guint has_focus_chain : 1;
};

GtkContainer的成员中有一个GtkWidget,而再来看到gtkwidget.h:
typedef struct _GtkWindow          GtkWindow;
...
struct _GtkWidget
{
  /* The object structure needs to be the first
   *  element in the widget structure in order for
   *  the object mechanism to work correctly. This
   *  allows a GtkWidget pointer to be cast to a
   *  GtkObject pointer.
   */
  GtkObject object;
    ...
};


GtkWidget中有个成员为GtkObject,以如此的链结关系来维持物件上的继承关系架构,而在gtk_window_set_title()函式的使用例子中:
gtk_window_set_title(GTK_WINDOW(window), "哈啰!GTK+!");

GTK_WINDOW是一个巨集,用来进行指标型态转型动作:
#define GTK_WINDOW(obj)
          (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_WINDOW, GtkWindow))


G_TYPE_CHECK_INSTANCE_CAST巨集定义在GLib的gtype.h(
/usr/include/glib-2.0/gobject/gtype.h)中:
#define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type)   
            (_G_TYPE_CIC ((instance), (g_type), c_type))


G_TYPE_CHECK_INSTANCE_CAST巨集会检查instance是否为g_type的一个实例,如果不是的话就发出警示讯息,若是的话就将指标转型为c_type型态(参考 G_TYPE_CHECK_INSTANCE_CAST 线上文件说明)。

即便在熟悉C++、Java等支援物件导向程式语言的人来说,这样的架构在物件导向的概念上并不完整,但确实在易读与维护性上加强了不少。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章