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.






