Molte persone chiedono frequentemente perché GTK+ è stato scritto nel linguaggio C piuttosto che in un linguaggio orientato agli oggetti. La risposta è che C è maggiormente portabile e disponibile su praticamente qualunque piattaforma, più di ogni altro linguaggio esistente. Tuttavia, anche se C non fornisce istuzioni e/o sintassi per la programmazione orientata agli oggetti, non proibisce un approccio di questo genere.
GTK+ implementa un proprio sistema di oggetti, che offrono caratteristiche standard come l'ereditarietà e le funzioni virtuali. Nella tradizione dei linguaggi come Lisp, Smalltalk e Java, il sistema od oggetti di GTK+ è maggiormente incentrato sul runtime rispetto a C++, permettendo interazioni con linguaggi interpretati in modo potente e flessibile.
Potete ricordare dal il capitolo Fondamenti di GTK+ che i widget sono tipi particolari di GtkObject. Qualunque oggetto con che possiede un GtkWidget nelle sue classi di base è un widget. I widget rappresentano una regione dello schermo: la maggior parte di questo sono elementi di una interfaccia grafica, come pulsanti o meno. Non esiste alcuna relazione tra GtkObject e l'interfaccia grafica: il sistema di oggetti può essere utilizzato in applicazioni non grafiche.
Questo capitolo espone in dettagli il sistema a oggetti di GTK+, fornendo una idea di cosa accade dietro le quinte di qualunque applicativo GTK+. Prima o poi avrete bisogno di queste informazioni: per scrivere un vostro oggetto, eseguire il debug di altri preesistenti, oppure comprendere a livello concettuale il codice di GTK+.
Ciascun GtkObject ha due componenti essenziali: una struttura che rappresenta una istanza dell'oggetto, e una che ne rappresenta la classe. In generale, la struttura di istanza contiene puntatori alle funzioni della classe. La struttura della classe può inoltre contenere informazioni sulla classe, tuttavia, si è soliti utilizzare variabili static nel file .c dove viene implementato l'oggetto. Se avete familiarità con C++, la struttura della classe è equivalente ad una vtable, ed è l'unica struttura scritta manualmente. Contiene funzioni virtuali per il determinato tipo di oggetto.
Ecco le strutture utilizzate per il GtkButton:
typedef struct _GtkButton GtkButton;
typedef struct _GtkButtonClass GtkButtonClass;
struct _GtkButton
{
GtkBin bin;
GtkWidget *child;
guint in_button : 1;
guint button_down : 1;
guint relief : 2;
};
struct _GtkButtonClass
{
GtkBinClass parent_class;
void (* pressed) (GtkButton *button);
void (* released) (GtkButton *button);
void (* clicked) (GtkButton *button);
void (* enter) (GtkButton *button);
void (* leave) (GtkButton *button);
};
|
Notare che il primo membro della struttura _GtkButton è GtkBin. Questo perché GtkButton è una sottoclasse di GtkBin. (GtkBin è un GtkContainer che può contenere un unico widget al suo interno..) Dato che GtkBin è il primo membro, possiamo eseguire senza alcun problema il cast da GtkButton a GtkBin. Nella struttura struct _GtkButtonClass viene applicato lo stesso principio, dove GtkBinClass è il primo membro.