I tipi e gli oggetti in GTK+

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+.

Strutture di oggetti e classi

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.