
Un altro problema riguarda il fatto che Point_ctor() chiama il selettore della superclasse e di conseguenza non necessita di importare gli oggetti parametri come faceva Point_draw().
E' probabilmnete una buona idea se abbiamo un modo per dire ogni volta a ooc se vogliamo importare o meno e verificare o meno gli oggetti.
if there is a new metaclass for all methods in %- void draw (const void * _self) { // selector % PointClass Circle: Point { // header int rad; // object component %}
Questa descrizione semplicissima contiene sufficienti informazioni che potremmo giàù generare i file di interfaccia. Ecco un pattern invece per dare un'idea di come ooc creerebbe Point.h.
#ifndef Point_h #define Point_h #include "Object.h" extern const void * Point; for all methods in % void move (void * self, int dx, int dy); if there is a new metaclass extern const void * PointClass; for all methods in %- void draw (const void * self); void initPoint (void); #endif
Le parti indicate in grassetto si riferiscono a pattern comuni a tutti i file di interfaccia. Il font standard indica le informazioni che ooc deve leggere nella descrizione di classe e inserire all'interno dei file interfaccia. Le liste dei parametri sono da manipolare: _self o const _self sono convertite in adeguati puntatori, gli altri parametri possono essere copiati direttamente.
const struct PointClass * class = classOf(_self); assert(class -> draw); class -> draw(self); } // superclass selector void super_draw (const void * class, const void * _self) { const struct PointClass * superclass = super(class); assert(_self && superclass -> draw); superclass -> draw(self); }
Se la descrizione di classe definisce una nuova metaclasse, possiamo generare tutti i selettori e i selettori della superclasse per tutti i nuovi metodi linkati dinamicamente. Se vogliamo farlo, in ogni selettore possiamo usare cicli di iterazione sui parametri e verificare che non ci siano puntatori null al posto degli oggetti.
if there is a new metaclass // metaclass constructor static void * PointClass_ctor (void * _self, va_list * app) { { struct PointClass * self = super_ctor(PointClass, _self, app); typedef void (* voidf) (); voidf selector; va_list ap = * app; while ((selector = va_arg(ap, voidf))) { voidf method = va_arg(ap, voidf); for all methods in %- if (selector == (voidf) draw) { * (voidf *) & self -> draw = method; continue; } } return self; }
Con un'iterazione sulle definizioni dei metodi nella descrizione di classe possiamo completamente generare i costruttori della metaclasse. In qualche modo, comunque, dovremmo dire ad ooc quale è l'header appropriato del metodo da usare per ctor() - un progetto diverso potrebbe decidere di utilizzare convenzioni diverse per i costruttori.
if there is a new metaclass // metaclass constructor static void * PointClass_ctor (void * _self, va_list * app) { { struct PointClass * self = super_ctor(PointClass, _self, app); typedef void (* voidf) (); voidf selector; va_list ap = * app; while ((selector = va_arg(ap, voidf))) { voidf method = va_arg(ap, voidf); for all methods in %- if (selector == (voidf) draw) { * (voidf *) & self -> draw = method; continue; } } return self; }
La funzione di inizializzazione dipende da un'iterazione su tutti i metodi linkati dinamicamente e sovrascritti nell'implementazione stessa.
