Programmazione orientata agli oggetti in ANSI-C. Object Rivisitato

Nella sezione 7.1 abbiamo visto che per lavorare su Point abbiamo bisogno di raccogliere le informazioni dalle sue superclassi, fino ad arrivare alla classe radice della gerarchia.

Così come dobbiamo specificare Object? Non avrà senso definire Object come parte del programma awk. La soluzione ovvia è scrivere un file di descrizione di classe:

#include 
#include 
#include 
%prot
#include 
% Class Object {
const Class @ class; // object’s description
%
void delete (_self); // reclaim instance
const void * classOf (const _self); // object’s class
size_t sizeOf (const _self); // object’s size
%—
void * ctor (_self, va_list * app); // constructor
void * dtor (_self); // destructor
int differ (const _self, const Object @ b); // true if !=
int puto (const _self, FILE * fp); // display
%}

Sfortunatamente, questo è un caso speciale: come radice della gerarchia, Object non ha superclassi ed essendo la prima metaclasse, Class non ha superclassi. Solo una delle descrizioni di classe ha questa proprietà, di conseguenza dobbiamo fare in modo che ooc riconosca una sintassi speciale per l'header della classe come descrizione delle classi di 'root e di 'metaroot.

Class presenta anche un altro problema: abbiamo visto nella sezione 7.1 che le nuove metaclassi possono essere dichiarate con una nuova classe perchè esse possono avere solo i link ai metodi come nuovi componenti. Class è la prima metaclasse e deve per forza avere qualche componente extra:

% Class Class: Object {
const char * name; // class’ name
const Class @ super; // class’ superclass
size_t size; // object’s memory size
%
Object @ new (const _self, ...); // create instance
const void * super (const _self); // class’ superclass
%}

Ne consegue che la nostra sintassi per la descrizione di classe è sufficiente per descrivere Class. C'è un altro caso particolare per ooc: è la sola classe per la quale è ammesso avere essa stessa una metaclasse.

Se mettiamo entrambe le descrizione nello stesso file di descrizione di classe Object.d e se permettiamo che Object preceda Class, la ricerca per le descrizioni di classe in ooc termineranno tutte da esso stesso. Il nostro database è completo.

Potremmo scrivere l'implementazione di Object e Class a mano – si può fare a patto che sia utilizzato per generare una singola implementazione. Tuttavia, il nostro meccanismo di generazione del report è valido anche per essere adattato ad Object.

I file interfaccia per Point e Object sono abbastanza simili, con l'eccezione che Object non ha alcuna interfaccia di superclasse da includere e non dichiara una funzione di inizializzazione. Il corrispondente file di report h.rep viene usato più volte quindi è meglio evitare di riempirlo di costrutti condizionali che non sono generalmente necessari. Al contrario, andiamo ad aggiungere un parametro alla linea di domando di ooc.

$ ooc —R Object —h > Object.h

Questo parametro impone di caricare il file di report speciale denominato h-R.rep che è appositamente pensato per adattarsi alla classe radice della gerarchia. Entrambi i file di report generano la maggior parte degli header dei metodi e possono condividere altri file di report, ad esempio il file header.rep che contiene il report header utilizzato in entrambe le classi.
Analogamente, i file di rappresentazione di Point e Object hanno molto in comune e useremo -R per caricare un file di report r-R.rep al posto di r.rep

$ ooc —R Object —r > Object.r

Object.r non ha una rappresentazione della superclasse da includere, e la struttura della metaclasse per Class inizia con i componente extra. Il codice comune per dichiarare i selettori della superclasse e i metodi come componenti della metaclasse si trova in un altro file di report di nome va.rep.

Infine, possiamo usare l'opzione -R e un altro file di report c-R.rep al posto di c.rep per aiutare nella generazione dell'implementazione:

$ ooc —R Object Object.dc > Object.c

ooc aggiungerà gli statement per l'include e si occuperà del preprocessing degli header dei metodi in Object.dc così come in ogni altro file di implementazione. La sola differenza risiede nell'implementazione di %Init. Possiamo ancora lasciare che sia ooc a generare i selettori e i selettori della superclasse, ma dobbiamo codificare l'inizializzazione statica delle descrizioni di classe mostrate nella sezione 6.7, inizializzazione da codificare a mano.

Ci poniamo quindi l'interrogativo su come debba essere scritto il costruttore della metaclasse Class_ctor(). Se lo facciamo a mano in Object.dc dobbiamo codificare essenzialmente il ciclo che analizza le coppie selettore/metodo due volte: una volta in Object.dc per Class_ctor() e una volta nel file di report c.rep per tutte le altre classi. Ma abbiamo sufficienti informazioni per farlo in c-R.rep. Se poi ipotizziamo che i primi argomenti del costruttore appaiono nell'ordine dei componenti specificati in Classe possiamo generare l'intero costruttore e quindi condividere il codice di loop come un report meta-ctor-loop in un file comune etc.rep.

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend