Tenere traccia di tutti gli oggetti di una classe


9

Sono nuovo nella programmazione orientata agli oggetti e continuo ad affrontare questo problema. (Sto programmando in Java) Sono stato un po 'riluttante a chiedere questo, dal momento che sembra un problema di base, ma non riesco a trovare alcuna informazione su di esso, o domande su di esso qui, e nessuna delle i libri di testo che ho letto (a un livello abbastanza semplice ovviamente) hanno toccato questo problema:

Spesso ho bisogno di tenere traccia di tutti gli oggetti di una classe che sono stati creati, per scorrere attraverso di essi per vari scopi. In questo modo attualmente scrivo programmi, molti oggetti fanno riferimento solo ad altri oggetti, il che significa che non ho array o raccolte con cui fare riferimento a tutti.

Immagino che, poiché questa sembra una necessità così basilare in OOP, dovrebbe esserci un modo abbastanza istituzionalizzato e semplice di procedere? È consuetudine tenere un elenco separato di tutti gli oggetti di una classe?

Ho pensato a una matrice o collezione statica, alla quale attraverso il suo costruttore sarebbe stato aggiunto ogni nuovo oggetto creato. Ciò tuttavia non funzionerebbe con le sottoclassi, poiché i costruttori non sono ereditati?

Mi rendo conto che questa domanda potrebbe non avere una risposta facile; Spero solo che qualcuno possa illuminarmi un po 'su questo argomento. Mi sento come se mi mancasse una conoscenza centrale qui.


5
Un esempio più specifico del tracciato e del tracker potrebbe essere d'aiuto. Questo problema viene gestito in molti modi diversi a seconda del contesto, di come vengono utilizzati e così via.
Giustino l'

2
Penso che potresti affrontare il problema dalla parte sbagliata. Non è molto comune avere bisogno di un elenco di tutte le istanze di una data classe, e averne una causerebbe tutti i tipi di problemi di progettazione (perché ora anche le istanze create in contesti totalmente non correlati dipendono l'una dall'altra attraverso questo elenco).
tdammers,

1
"iterate attraverso di essi per vari scopi" ... come ...? Generalmente, un oggetto ha un "proprietario" (non un termine formale, più semplicemente una dichiarazione sulla semantica del programma), e non è per nessun altro avere "vari scopi" con l'oggetto.
AakashM,

Risposte:


8

Non so perché devi tenere un elenco di tutte le istanze di una classe.

Ciò causerebbe una perdita di memoria poiché tali oggetti non verranno mai eliminati, poiché l'elenco continuerà a fare riferimento a loro dopo che nessun'altra classe lo fa.

Ma se vuoi davvero seguire quel percorso:

  1. Usa il modello Factory. Una classe factory con metodi che instanciano la classe e restituiscono gli oggetti. In questo modo hai un punto centralizzato per controllare le istanze.
  2. Utilizzare il modello Singleton per contenere un elenco o elenchi che contengono le istanze.
  3. Fai in modo che la fabbrica inserisca ogni oggetto di un certo tipo in un elenco dopo averli creati.

A proposito: i costruttori sono ereditati.


Ovviamente puoi fornire alla fabbrica un metodo "dispose" che rimuove l'istanza dal suo elenco di istanze monitorate. Ma non c'è modo di invocarlo esplicitamente. Oppure dai all'istanza un metodo dispose che inneschi il metodo dispose nella sua factory, che ha lo stesso inconveniente ma è leggermente più probabile che venga effettivamente chiamato poiché è più vicino all'utente, più visibile.
jwenting

@jwenting Certo che è un modo. Ma ciò creerebbe brutte e inutili dipendenze tra le classi e la fabbrica. Le lezioni non dovrebbero sapere nulla della fabbrica che le crea.
Tulains Córdova,

quindi facendo in modo che la fabbrica tenga traccia di ciò che crea, piuttosto che l'oggetto che dice alla fabbrica di registrarlo ...
jwenting

Un singleton tecnicamente conterrebbe tutti i casi immagino. L'unica singola istanza.
Rig

3

Va notato che i riferimenti deboli possono essere utilizzati in combinazione con le altre soluzioni fornite per consentire al garbage collector di disporre di oggetti tracciati quando non vengono più citati altrove. Ciò elimina le perdite di memoria senza che sia necessario altrove il codice per smaltire manualmente gli oggetti, o altrimenti preoccuparsi che vengano monitorati. È possibile fornire un ReferenceQueue per ricevere la notifica dei riferimenti agli oggetti che sono stati liberati.

Ho pensato a una matrice o collezione statica, alla quale attraverso il suo costruttore sarebbe stato aggiunto ogni nuovo oggetto creato. Ciò tuttavia non funzionerebbe con le sottoclassi, poiché i costruttori non sono ereditati?

I costruttori di classi base vengono invocati prima dei costruttori di classi derivate. Ogni classe ha almeno un costruttore e i costruttori non possono essere sovrascritti.


2

Quando si creano giochi, le persone a volte vogliono una raccolta "autogestita" di ogni tipo di oggetto di gioco.

Un'implementazione si presenta così:

public class Car {

    static ArrayList<Car> list = new ArrayList<Car>();

    public Car() {
        list.add(this);
    }

    void kill() {
        list.remove(this);
    }

    static public void updateAll()
    {
        for (int i = list.size() - 1; i >= 0; i--)
        {
                list.get(i).update();
        }
    }

    public void update()
    {
        //update logic
    }
}

In questo modo i metodi che manipolano la raccolta possono essere dichiarati statici mentre i metodi non statici manipolano un'istanza (updateAll vs. update).

Mentre va bene per scenari molto semplici, con una complessità anche moderata, di solito è meglio creare classi manager separate.


1
Puoi scrivere direttamente static ArrayList<ListeStatic> list = new ArrayList<ListeStatic>();e sopprimere statc {..}
cl-r l'

2
Nel metodo Java il nome inizia con una lettera minuscola:uptdateAll(){..;}
cl-r,

oops ... è passato un po 'di tempo da quando ho mandato in onda la mia java in pubblico
Kelly Thomas l'

@KellyThomas Un'auto si aggiunge a un elenco, rimuovendosi da essa. Sembra innaturale.
Tulains Córdova,

1
@ CayetanoGonçalves come campo statico è un elenco condiviso da tutte le istanze.
Kelly Thomas,

2

Prova a pensare al contesto. Quando si crea un oggetto, lo si fa in un determinato contesto. Ad esempio, se il tuo gioco prevede di sparare agli alieni, la tua app creerà sempre nuovi oggetti alieni. Verranno visualizzati in un campo chiamato Spazio (che potrebbe essere la classe che rappresenta l'interfaccia utente principale).

È perfettamente naturale che Space abbia una proprietà chiamata currentAliens, che sarebbe una matrice, alla quale aggiungi ogni nuovo alieno che crei. Se vuoi consentire al tuo utente di rompere il tessuto dello spaziotempo e distruggere tutti gli alieni contemporaneamente, dovrai scorrere attraverso quella raccolta e distruggere ogni oggetto.

Se desideri avere accesso a questa raccolta di alieni all'interno di altre parti della tua app (ad esempio, da una pagina Impostazioni, in cui potresti voler consentire agli utenti di spazzare via determinati tipi di alieni in un colpo solo), il tuo contesto Impostazioni sarebbe è necessario disporre dell'accesso all'oggetto Space.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.