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等支援物件導向程式語言的人來說,這樣的架構在物件導向的概念上並不完整,但確實在易讀與維護性上加強了不少。

你可能感兴趣的:(C++,c,C#)