Home
Accesso / Registrazione
 di 

Programmazione orientata agli oggetti in ANSI-C. Implementazione della superclasse – Punto

Implementazione della superclasse – Punto

L'interfaccia di dato astratto in Point.h contiene le seguenti linee:

extern const void * Point; /* new(Point, x, y); */
void move (void * point, int dx, int dy);

Possiamo riciclare i file di new.? Illustrati in un altro articolo con la differenza di eliminare molti metodi e di aggiungere draw() in new.h.

void * new (const void * class, ...);
void delete (void * item);
void draw (const void * self);

La descrizione di tipo struct Class in new.r dovrebbe corrispondere alle dichiarazioni dei metodi in new.h

struct Class {
size_t size;
void * (* ctor) (void * self, va_list * app);
void * (* dtor) (void * self);
void (* draw) (const void * self);
}

Il selettore draw() viene implementato in new.c il quale rimpiazza i selettori quali differ() introdotti nella sezione 2.3. draw() viene codificato nello stesso stile del differ()

void draw (const void * self)
{ const struct Class * const * cp = self;
assert(self && * cp && (* cp) —> draw);
(* cp) —> draw(self);
}

Dopo queste considerazioni preliminare, possiamo occuparci del vero lavoro, ossia di scrivere praticamente il file Point.c che altro non è che l'implementazione di punti. Ancora una volta, lavorando in maniera orientata agli oggetti ci ha aiutato ad identificare precisamente ciò che dobbiamo fare: dobbiamo decidere sulla rappresentazione e sull'implementazione di un costruttore, un distruttore, del linkage dinamico di draw() e del metodo invocato staticamente move(). Se ipotizziamo di lavorare in un ambiente bidimensionale, basato sulle coordiante cartesiane, possiamo quindi scegliere la facile rappresentazione:

struct Point {
const void * class;
int x, y; /* coordinates */
};

Il costruttore deve inizializzare le coordinate .x e .y – cosa che è praticamente la solita routine

static void * Point_ctor (void * _self, va_list * app)
{ struct Point * self = _self;
self —> x = va_arg(* app, int);
self —> y = va_arg(* app, int);
return self;
}

Non avremo bisogno di un distruttore perchè non abbiamo risorse da reclamare prima che entri in gioco la funzione delete(). In Point_draw() stampiamo le coordinate correnti in un modo che pic può comprendere:

static void Point_draw (const void * _self)
{ const struct Point * self = _self;
printf("\".\" at %d,%d\n", self —> x, self —> y);
}

Questo codice seguente invece si prende cura di tutti i metodi linkati dinamicamente e possiamo definire il descrittore di tipo, dove un puntatore nullo rappresenta il distruttore (che non esiste)

static const struct Class _Point = {
sizeof(struct Point), Point_ctor, 0, Point_draw
};
const void * Point = & _Point;

move() non è linkato dinamicamente, così omettiamo static per esportarlo da Point.c e non precediamo il suo nome con il nome della classe Point

void move (void * _self, int dx, int dy)
{ struct Point * self = _self;
self —> x += dx, self —> y += dy;
}

Ecco conclusa la implementazione dei punti in Point.? assieme al supporto per il dynamic linkage in new.?.

 

 

Scrivi un commento all'articolo esprimendo la tua opinione sul tema, chiedendo eventuali spiegazioni e/o approfondimenti e contribuendo allo sviluppo dell'argomento proposto. Verranno accettati solo commenti a tema con l'argomento dell'articolo stesso. Commenti NON a tema dovranno essere necessariamente inseriti nel Forum creando un "nuovo argomento di discussione". Per commentare devi accedere al Blog

 

 

Login   
 Twitter Facebook LinkedIn Youtube Google RSS

Chi è online

Ci sono attualmente 41 utenti e 150 visitatori collegati.

Ultimi Commenti