| 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;
GtkContainer的成員中有一個GtkWidget,而再來看到gtkwidget.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; }; 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等支援物件導向程式語言的人來說,這樣的架構在物件導向的概念上並不完整,但確實在易讀與維護性上加強了不少。 |