Confronto Array di Strutture verso Collezione di Classi
Indice
Confronto Array di Strutture verso Collezione di Classi
Per chi proviene in Gambas da MS VB la definizione e la gestione di strutture dati personalizzate può essere fonte di
confusione.
In genere, l'utente medio VB è abituato ad utilizzare array di strutture ('custom types').
Altri preferiscono utilizzare le Classi, con relative proprietà e metodi, e le Collection; in questo caso l'approccio a
Gambas non comporta variazioni sostanziali.
La differenza sostanziale tra Array e Collection è data dalla differente metodologia di accesso agli elementi.
Gli Array sono per loro natura 'posizionali', ovvero la posizione in memoria è sequenziale e stabilita dalla dimensione e
dall'indice progressivo del singolo elemento.
Le Collection sono gestite autonomamente dal compilatore e la posizione degli elementi non è determinata; l'accesso avviene
tramite un indice chiave ('Key').
Lo scopo di questo documento è di fornire alcune informazioni sulle differenze tra i due approcci, con vantaggi e svantaggi,
e una sintetica valutazione prestazionale.
Per ciascun approccio saranno presentate le 3 operazioni fondamentali di gestione liste, ovvero Accesso, Aggiunta,
Eliminazione.
Definizione di STRUTTURE
Per gli esempi che seguino consideremo una semplicissima struttura dati composta da due proprietà, definita in Gambas con:
PUBLIC STRUCT Contatto
ID As Integer
nome As String
telefono As String
END STRUCT
Definizione di CLASSI
L'uso di classi comporta la consueta creazione di un documento di classe (es. clsContatto) che esponga le stesse
proprietà viste sopra e dei metodi per la gestione delle stesse.
Si crea dunque il nuovo documento 'clsContatto' (Attenzione: deve avere la definizione all'inizio CREATE
STATIC
).
'Class clsContatto
CREATE STATIC
PROPERTY Nome As String
PROPERTY Telefono As String
PRIVATE $iID As Integer 'proprietà utilizzata internamente per generare una nuova chiave
PRIVATE $sNome As String
PRIVATE $iTelefono As String
E' consigliabile usare questo approccio che prevede di 'nascondere' le proprietà interne della classe ed accedere ad esse
solo tramite chiamate ai metodi pubblici esposti.
In questo modo, oltre alla maggiore flessibilità di modifica della classa, si delega alla classe il compiti di validazione
dei parametri.
ARRAY
In Gambas gli array di strutture possono essere statici o dinamici, ovvero a dimensioni prestabilite oppure variabili.
Array statici
Gli Array statici sono di scarso interesse in quanto la loro dimensione è 'hard coded' nel sorgente, quindi sono per
niente flessibili. Ciò che segue è quindi sono allo scopo di completezza d'informazione e non sarà utilizzato negli esempi.
NOTA: in VB non esiste il concetto di Array statico in quanto può essere in qualsiasi momento ridimensionato con le
istruzioni REDIM [PRESERVE}
La dichiarazione di un array statico di 10 strutture Contatto si scrive:
PUBLIC miaAgenda[10] as STRUCT Contatto
Array dinamici
La dichiarazione di Array dinamici è sottilmente, ma sostanzialmente, diversa:
PUBLIC miaAgenda as NEW Contatto[]
Si noti l'ovvia assenza del numero di elementi, l'uso di NEW e la diversa posizione delle parentesi quadre.
NOTA 1: per Gambas gli Array dinamici non sono altro che degli oggetti (classi), per cui valgono proprietà e metodi
ereditati dalla classe madre 'Object'.
Ne consegue che l'utilizzo come Array piuttosto che come classi è più una scelta dell'utilizzatore che pratica, tranne
nell'enumerazione degli elementi.
NOTA 2: se si vuole utilizzare un Modulo esterno al Form principale (per pulizia del codice) per la gestione dei
dati, è obbligatorio copiare esattamente la dichiarazione della struttura ANCHE nel Form.
Per ridimensionate l'array (in VB si scriverebbe Redim Preserve miaAgenda(11)
); in Gambas occorre procedere in
3 fasi:
1. si aumenta la dimensione dell'array con: miaAgenda.Resize(11)
2. si istanzia un nuovo elemento 'Contatto' con: nuovoContatto as New Contatto
3. si aggiunge il nuovo elemento vuoto con: miaAgenda.Add(nuovoContatto)
Enumerazione e accesso agli elementi
Accedere a tutti (enumerazione) o ad un elemento dell'Array è identico al metodo usato in VB, con l'unica avvertenza di
usare le parentesi quadre invece che tonde, per cui:
Dim cliente AS Contatto
Dim numero AS String
Dim k as Integer
'per recuperare il valore di un campo dal record n°5:
numero = miaAgenda[5].telefono
'per recuperare l'intero record dall'agenda:
For k=1 To miaAgenda.Count
cliente = miaAgenda[k]
....
Next
Inserimento di elementi
Si incrementa come prima cosa la dimensione dell'array, come già visto, e poi si procede ad aggiungere i nuovi valori:
Static IdCount As Integer
Dim nuovoContatto As Contatto
IdCount = IdCount + 1
miaAgenda.Resize(miaAgenda.Count+1)
nuovoContatto as New Contatto
nuovoContatto.ID = IdCount
nuovoContatto.Nome = "Pippo"
nuovoContatto.Telefono = 333-123456
miaAgenda.Add(nuovoContatto)
Cancellazione elementi
In VB l'eliminazione di un elemento richiede lo spostamento di tutti gli elementi superiori a quello voluto e
successivamente il ridimensionamento dell'array. Gambas mette invece a disposizione il metodo Remove che elimina
l'elemento e sposta automaticamente gli elementi superiori se esistono.
'nota: Indice è il numero dell'elemento da cancellare, passato alla funzione come parametro
miaAgenda[Indice].Remove
COLLECTION
La Collection è una rappresentazione dei dati estremamente potente, versatile e semplice in quanto si compone
di solo una coppia di informazioni:
- la KEY (chiave) di accesso: una stringa che deve avere un valore univoco e non nullo (se Null, l'elemento
'sparisce', ovvero viene eliminato).
- il VALUE (valore): può essere qualsiasi cosa (variabile semplice, array, oggetti e anche altre
Collection).
La Key può essere semplicemente un numero indice convertito in stringa per cui spesso l'uso delle Collection è
concettualmente simile all'uso degli Array.
La definizione e l'instanziamento di una Collection, che è un Oggetto, è del tutto uguale a quelle degli tipi di variabile,
per cui:
Pubblic miaAgenda as Collection
...
miaAgenda = New Collection
Enumerazione ed accessi agli elementi
Dim cliente AS clsContatto
Dim tel as String
'Utilizzando il campio chiave (es. Codice Fiscale), si accede direttamente al singolo elemento:
tel = miaAgenda[CodiceFiscale].Telefono 'Attenzione: la chiave deve essere una stringa!
L'enumerazione degli elementi utilizza la notazione For Each come per tutti gli altri oggetti.
For Each cliente In miaAgenda
Print cliente.Nome
....
Next
Inserimento di elementi
Occorre innanzitutto definire una nuova chiave; supponiamo di usare per questo il campo Telefono (certamente univoco).
Potrebbe però essere anche un valore esterno alla classe clsContatto, come un numero progressivo.
Static IdCount As Integer
Dim nuovoContatto As clsContatto
IdCount = IdCount + 1
nuovoContatto as New clsContatto
nuovoContatto.Nome = "Pippo"
nuovoContatto.Telefono = 345-987654
miaAgenda.Add(nuovoContatto, CStr(IdCount)) 'notare l'uso di IdCount come chiave
Cancellazione elementi
Come anticipato, per cancellare un elemento è sufficiente porre a Null la chiave, oppure utilizzare anche qui il metodo 'Remove':
miaAgenda[IdCount]=Null
In realtà, è altamente consigliabile verificare prima che la chiave esista, per esempio:
'oppure:
miaAgenda[IdCount].Remove
If miaAgenda[IdCount].Exist Then miaAgenda[IdCount].Remove
E' importante notare come nel caso delle Collection non sia necessario ridimensionare la struttura in quanto si adegua da
sè.
SCHEMA DI IMPLEMENTAZIONE DI CLASSI E COLLECTION
Per riassumere quanto vito nel caso di utilizzo di classi e collection (strategia suggerita), viene di seguito riportato uno schema sintetico dei documenti e delle dichiarazioni necessarie.
Documento | Dichiarazioni |
---|---|
Form Main | Chiamate ai metodi clsAgenda.miaAgenda[chiave]... |
Classe 'clsAgenda' |
PUBLIC miaAgenda As Collection |
Classe 'clsContatto' |
PROPERTY Nome As String |
CONFRONTO
Sia gli array di strutture che le collection di classi sono per Gambas degli oggetti, per cui l'approccio è sotto molti
punti di vista simile.
Per chi proviene da VB le Strutture sono forse più familiari e forse più semplici da utilizzare dalle Classi.
Occorre però anche considerare la diversa modalità di creazione e aggiunta di elementi in Gambas rispetto a VB, che
'appesantisce' in una certa misura la gestione.
Le Classi da parte loro hanno numerosi vantaggi in termini di leggibilità e di manutenzione del codice, nonchè offrono
capacità di estensione d'uso sconosciute alle Strutture.
Basti pensare all'ereditarietà delle Classi per cui si può avere una classe base e numerose classi figlie, senza dovere
ripetere tutto il codice, e racchiudere il tutto in una Collection.
Inoltre, e questo è fondamentale per la sicurezza verso bachi e modifiche del codice nella Main, le classi consentono
l'incapsulamento del codice, delegando tutte le procedure di accesso e verifica di congruità dei dati alla classe stessa.
Questo permette tra l'altro di riutilizzare la stessa classe in altri progetti.
Dal punto di vista prestazionale, la valutazione sui tempi di esecuzione è delegata ad una seconda parte di questo
documento che sarà rilasciata al più presto,
insieme ad un programma di esempio e di test.
--Orionis (discussioni) 08:11, 30 giu 2014 (MDT)