Newsgroup: it.comp.java
Titolo: Un buon metodo per archiviare i dati

Il mio problema è questo:
vorrei creare una classe sufficentemente elastica che mi consenta di
archiviare dati. Ciò significa che dovrebbe poter contenere:
elenchi di oggetti, metodi per lavorare con l'elenco e possibilità si
salvare/caricare su/da disco.
La soluzione che ho pensato è quella di estendere un Vector. Ora, forse
il Vector non è la lista più ottimizzata (ma a me serve una lista ad
accesso random, non ad accesso sequenziale), cmq il problema è un altro.
diciamo che creo una:
class ExtVector extends Vector {}
qui ho un Vector di object e i metodi per lavorarci. Aggiungo due metodi
per salvare e caricare da file (e/o da Stream), e un metodo toString()
personalizzato.
Questo per ottenere un singolo oggetto del mio archivio. Questo oggetto
conterrà solo i valori dei campi del singolo elemento del mio archivio,
e non i nomi dei campi.
A questo punto faccio un'altra classe
class ExtVectorList extends Vector{
	ExtVector nomi; /* i nomi dei campi all'interno dell'archivio. In
questo modo sono scritti 				una volta sola e valgono per tutti gli
elementi della ExtVectorList*/
	...
}
la ExtVectorList è ancora un Vector di object. Ora dovrò scrivere ancora
dei metodi personalizzati per salvare e caricare (che sovrascriveranno
quelli di ExtVector). Questi metodi, giocoforza, dovreanno richamare
(all'interno di un ciclo) i metodi di salvataggio di ogni loro elemento,
tipo
for (int i = 0;i<zize();i++)
	elementAt(i).saveToFile();
e qui non può funzionare, dato che l'elemento i-esimo della
ExtVectorList è un Object, quindi non ha il metodo saveToFile().
Al che la mia soluzione sarebbe: modificare la ExtVectorList in modo che
non sia più una lista di oggetti, ma una lista di ExtVector, per poter
richiamare tutti i metodi peculiari della ExtVector.
Questo mi consentirebbe di creare nuovi archivi senza cambiare
praticamente codice. Infatti se voglio archiviare CD, la mia classe
ExtVectorList sarà così:
nomi (che è un ExtVector) avrà valori tipo: [Titolo, Autore, Anno]
poi ogni elemento della ExtVectorList sarà una ExtVector che conterrà a
sua volta una lista di oggetti (nel mio caso semplici stringhe) che
saranno ad esempio
[Up, REM, 1998]
e così via. 
Per fare questo però DEVO rendere la ExtVectorList una lista di
ExtVector. Ho quindi pensato di: o "sovrascrivere" il campo 
protected Object elementData[];
con il campo
protected ExtVector elementData[];
dichiarato nella classe ExtVectorList 
Ora dovrei scrivere un nuovo metodo in sostituzione di elementAt() (dato
che non posso fare un override di quel metodo), e lo chiamo 
public synchronized ExtVector elemAt(int index)
che è uguale come codice a elementAt() solo che ritorna un oggetto della
classe che mi serve
Così però, oltre ad essere una soluzione brutta,  non funziona, in
quanto quanto richiedo elemAt(i) mi da sempre la NullPointerException.
in pratica lui va a riempire un array, che non è quello che poi
richiamo. Cmq, non ho approfondito, dato che non mi piace come metodo.
Dunque la soluzione sarebbe: dichiarare un altro campo
protected ExtVector elemData[];
e riscrivere un po' di metodi (quelli che mi servono), copiando
praticamente il codice dal Vector, ma sostituendo elemData con
elementData quando necessario. Così riempirei l'array giusto, l'altro
resta sempre vuoto, e tutto dovrebbe funzionare.
Ora, ammesso e non concesso che funzioni, vi sembra una soluzione
valida, oppure no ?
Io non vorrei aver incasinato troppo le cose, oppure che il tutto si
potesse risolvere in maniera altrettanto valida con metodi più
ortodossi.
Pensate però che così io avrei una lista di vettori che è il mio
database. Gli elementi del database sono a loro volta Vector, cosìcchè
non ho limiti ai campi che voglio inserire, e la posso usare per
qualunque tipo di dato.
Inoltre, utilizzando lo stesso metodo che userei per la ExtVectorList
(cioè quello di riempire non l'array di object, ma di farne uno di
ExtVector e riempire quello) potrei rendere l'ExtVector un semplice
array di stringhe (e non di object), magari chiamandolo StringVector, in
modo da velocizzare molte operazioni (eliminando quindi qualsiasi tipo
di cast). Sarebbe pià limitato, ma più veloce. 
Spero ci capiate qualcosa...
-- 
He who fights with monsters shoul look to it that he himself does not
become a monster... when you gaze long into the abyss the abyss also
gazes into you...

richiamare tutti i metodi peculiari della ExtVector.
Se nel Vector (che e` sotto il tuo controllo) metti sempre e soltanto
degli elementi di tipo ExtVector, bastera` che tu faccia poi il cast di
elementAt al tipo stesso, e.g.:
    ((ExtVector)elementAt(i)).saveToFile();
Questo e` il normale paradigma, in Java, per usare un Vector
(o altra struttura dati che fa da contenitore di Object, come ne
trovi in JGL, Java 1.2, ecc) come contenitore di Pippo, per un
qualsiasi tipo Pippo: rivestire il container, per controllare che gli
vengano messi dentro sempre e solo elementi del tipo giusto,
e, quando gli elementi vengono estratti, recuperarne il vero tipo
con un cast.
Non conviene dunque usare l'eredita` (extends) da Vector (o
altro contenitore), perche` allora nulla impedirebbe al codice
cliente della classe di usarla inappropriatamente; meglio il
contenimento, o incapsulamento che dir si voglia (la tua classe
ha una variabile d'istanza di tipo Vector, invece che estendere
Vector) e la delegazione (se c'e` qualche metodo che vuoi
solo "passare pari pari", devi farlo esplicitamente).
Questo naturalmente impedisce al codice cliente della tua
classe di usarla in metodi che si _aspettavano_ un argomento
di tipo Vector -- ma cio` e` appunto quel che ti serve, visto
che se no non avresti il controllo su cosa quei metodi possano
mettere dentro al contenitore (e poi, Vector ha troppi metodi
final, da addElement a trimToSize -- e` *decisamente* non
pensata per ereditarne...!).  Puoi ridurre questo problema
aggiungendo alla tua classe le opportune "implements" -- qui,
"implements java.util.Enumeration" (un codice-cliente che
deve solo esaminare gli argomenti sequenzialmente dovrebbe
prendere come argomento Enumeration, NON Vector -- sempre
lavorare al livello piu` astratto possibile, per generalita`!).
Alex