Programmazione orientata agli oggetti in ANSI-C. Classi di base astratte

Quando diamo un'occhiata ai metodi linkati dinamicamente, accordandoci su una nomenclatura per realizzare il callback, non sembra porre particolari limiti. Un metodo viene chiamato da un particolare oggetto, ossia quale codice viene eseguito per un callback dipende dall'oggetto in relazione ad uno specifico nome di metodo.

I metodi, tuttavia, possono essere dichiarati solo da una classe. Se vogliamo comunicare con un client nello stile delle funzioni di callback, dobbiamo postulare l'esistenza di una classe di base astratta con i necessari metodi di comunicazione e che l'oggetto client debba appartenere ad una sottoclasse per implementare questi metodi. Per esempio:

% OrderedClass: Class OrderedArray: Object {
%—
int cmp (const _self, int a, int b);
void swap (_self, int a, int b);
%}

Un algoritmo di ordinamento può usare cmp() per controllare due elementi di array tramite un indice e può usare swap() per sistemarli se si trovano fuori posto. L'algoritmo di ordinamento può essere applicato ad ogni sottoclasse di un OrderedArray che implementa questi metodi. OrderedArray stesso viene chiamato classe di base astratta perchè serve solo per dichiarare i metodi, questa classe non dovrebbe avere oggetti se i metodi non sono definiti.

Le classi di base astratte sono abbastanza eleganti da incapsulare le convenzioni sulle chiamate. Per esempio, in un sistema operativo ci potrebbe essere una classe di base astratto per una certa varietà di driver di dispositivo. Il sistema operativo comunica con ogni driver utilizzando i metodi della classe di base e per ogni driver ci si aspetta che questo implementi tutti questi metodi per comunicare con il dispositivo relativo.

Il succo è che tutti questi metodi di una classe di base astratta devono essere implementati dal client perchè saranno chiamati. Per un driver di un dispositivo è quasi ovvio questo fatto, ma un driver di dispositivo non è uno scenario sufficientemente rappresentativo per le funzioni di callback. Una finestra è un esempio più chiaro: alcuni client si devono occupare di certi aspetti che altri possono tralasciare – pertanto, perchè implementare tutti i metodi?

Una classe di base astratta restringe l'architettura della gerarchia delle classi. Senza l'ereditarietà multipla un client deve appartenere ad una particolare parte dell'albero delle classi alla cui radice c'è la classe di base astratta, senza particolare attenzione al ruolo corrente all'interno dell'applicazione. Ad esempio, consideriamo un client di una finestra che gestisce una lista di oggetti grafici. La soluzione elegante è lasciare che il client appartenga ad una sottoclasse di List ma l'implementazione di una finestra forza il client ad essere qualcosa come un WindowHandler. Come abbiamo discusso nella sezione 4.9 possiamo realizzare un aggregato e permettere che il client contenga un oggetto List, ma allora la nostra gerarchia di classi si evolve in relazione al sistema che rappresenta, piuttosto che in base alle necessità dei nostri problemi applicativi.

Infine, una classe di base astratta che definisce funzioni di callback tende a definire alcun componente privato per i suoi oggetti, ossia la classe dichiara ma non definisce metodi e gli oggetti non hanno uno stato privato. Mentre ciò non è in contrasto con il concetto di classe, è di fatto una situazione anomale e suggerisce che la classe di base astratta altro non è che una collezione di funzioni piuttosto che un insieme di oggetti e metodi.

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend