在物件导向的封装特性上,GTK以结构(structure)的方式来模拟类别,事实上GTK也直接称这些结构为类别,以建构GtkWindow的程式码为例:
在函式的组织上,与GtkWindow相关的函式,都是以gtk_window名称作为开头,gtk_window_new()就像是物件导向程式语言中的建构式,如果要设置GtkWindow的相关属性,例如标题名称:
gtk_window_set_title()的第一个参数接受GtkWindow指标,透过这种方式,让实际上属于全域的函 式,看来就像是专属于GtkWindow所使用,就如同物件上所带有的公开(public)方法(method)或成员函式(member function),而在私有(private)的模拟上,GTK使用static函式,例如在gtkwindow.c原始程式码中,可以看到:
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中有如下的定义:
...
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;
};
...
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是一个巨集,用来进行指标型态转型动作:
(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)中:
(_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等支援物件导向程式语言的人来说,这样的架构在物件导向的概念上并不完整,但确实在易读与维护性上加强了不少。