Questo è solo un sintomo sull'argomento, suggerisco caldamente di seguire i link qui.
" Un tipo di dati astratti definisce una classe di oggetti astratti che è completamente caratterizzata dalle operazioni disponibili su quegli oggetti. Ciò significa che un tipo di dati astratto può essere definito definendo le operazioni di caratterizzazione per quel tipo ". Liskov, Zilles: programmazione con tipi di dati astratti
Data la definizione informale di cui sopra, il seguente pseudo-codice può essere visto come un ADT:
type stack;
stack stack_create();
void stack_push(stack, T);
T stack_pop(stack);
Un punto è che nulla è noto sugli oggetti dello stack, eccetto ciò che può essere dedotto dalle operazioni disponibili per esso - nel caso precedente, stack_create
, stack_push
e stack_pop
. Ogni singolo dettaglio di implementazione e struttura è lasciato al lato dell'implementazione.
Ora, prendi una classe OO / python chiamata Stack
con i metodi push
e pop
.
class Stack:
def __init__(self):
...
def push(self, element):
...
def pop(self):
...
Se i suoi client sanno che esiste una classe chiamata Stack
e hanno accesso ad essa, un modo per vederlo è che gli oggetti sono caratterizzati dal fatto che sono istanze della classe Stack
la cui struttura contiene push
e pop
campi - indipendentemente dal fatto che siano chiamabili. I client sanno anche che possono ereditare da Stack
per creare qualcos'altro e così via.
Cioè, molto di più è noto / esposto ai clienti. Pertanto, questo tipo di Stack
è molto meno astratto di quello precedente (è esposto come una struttura concreta con due campi, ha una classe con cui puoi fare ereditarietà, ecc.). Di conseguenza, si potrebbe sostenere che questo tipo di Stack
non è un tipo di dati astratto conforme alla definizione data. Per essere più severi, si dovrebbe scrivere qualcosa del genere:
def create_stack():
...
def stack_push(stack, element):
...
def stack_pop(stack):
...
Ed ecco una possibile implementazione di esso (nel caso qui sotto, se hai già la classe sopra e vuoi solo renderla un ADT, è solo un wrapper):
def create_stack():
retur Stack()
def stack_push(stack, element):
return stack.push(element)
def stack_pop(stack):
return stack.pop()
Ora il client conosce solo le operazioni e le loro interfacce e le usa (e solo loro) per dedurre qual è il tipo "stack". Dall'esterno, non si sa nulla dell'attuale implementazione e struttura di una pila (a meno che non violino l'astrazione controllando la struttura del risultato di create_stack
).
Allo stesso modo, in C, puoi imitare questo ponendo queste dichiarazioni di funzione su un file di intestazione .h
(usando una dichiarazione diretta come tipo di pila, o semplicemente void*
), e poi, mettendo la definizione della struct e implementazioni di funzioni nel file .c
.
Nota sui sistemi di tipi : tutti i precedenti, ovviamente, non sono nel contesto delle lingue con controllo di tipo statico e sistemi di tipo buono - tale linguaggio potrebbe dover fornire determinati strumenti per rendere ragionevole ADT possibile. Inoltre, il modo in cui questo tema è esposto nel documento citato sopra, il controllo di tipo "strong" sembra essere una questione di preferenza dell'autore da solo; Non ho visto che fossero discussi o mostrati come un requisito degli ADT: il testo in realtà sembra essere cauto nel discutere del controllo dei caratteri come qualcosa di relativo ma non essenziale. Inoltre, la spiegazione di un "C approccio a ADT " (vedi sopra) è stato dato da William Cook, il ricercatore che ha scritto Programmazione orientata agli oggetti e tipi di dati astratti . [modifica] D'altra parte, Cook scrive :
" I tipi di dati astratti dipendono da un sistema di tipo statico per imporre l'astrazione del tipo.Non è un caso che i linguaggi dinamici utilizzino oggetti invece di tipi di dati astratti definiti dall'utente.Le lingue dinamiche in genere supportano tipi di dati astratti incorporati per i tipi primitivi, l'astrazione del tipo qui viene applicata dal sistema di runtime. "