Garder une trace de tous les objets d'une classe

9

Je suis nouveau dans la programmation orientée objet et je continue de rencontrer ce problème. (Je programme en Java) J'ai été un peu réticent à poser des questions à ce sujet, car il semble que ce soit un problème de base, mais je ne trouve aucune information à ce sujet, ou des questions à ce sujet ici, et aucune des les manuels que j'ai lus (à un niveau assez basique bien sûr) ont abordé cette question:

Souvent, je dois garder une trace de tous les objets d'une classe qui ont été créés, pour les parcourir à diverses fins. Comme j'écris actuellement des programmes, de nombreux objets sont uniquement référencés à partir d'autres objets, ce qui signifie que je n'ai pas de tableau ou de collection avec lequel les référencer tous.

J'imagine que, comme cela semble être une nécessité très fondamentale dans la POO, il devrait y avoir un moyen assez institutionnalisé et simple de procéder à ce sujet? Est-il habituel de conserver une liste séparée de tous les objets d'une classe?

J'ai pensé à un tableau ou à une collection statique, auquel à travers son constructeur, chaque nouvel objet créé serait ajouté. Cela ne fonctionnerait cependant pas avec les sous-classes, car les constructeurs ne sont pas hérités?

Je me rends compte que cette question pourrait ne pas avoir une réponse facile; J'espère juste que quelqu'un pourra m'éclairer un peu sur ce sujet. Je sens que si je manque ici d'un élément central de connaissances.

zxz
la source
5
Un exemple plus spécifique du suivi et du suivi pourrait vous aider. Ce problème est géré de différentes manières selon le contexte, la façon dont elles sont utilisées, etc.
JustinC
2
Je pense que vous abordez le problème du mauvais côté. Il n'est pas très courant d'avoir besoin d'une liste de toutes les instances d'une classe donnée, et en avoir une causerait toutes sortes de problèmes de conception (car maintenant même les instances créées dans des contextes totalement indépendants dépendent les unes des autres à travers cette liste).
tdammers
1
"les parcourir à diverses fins" ... comme ...? Généralement, un objet a un «propriétaire» (pas un terme formel, plus juste une déclaration sur la sémantique du programme), et il n'appartient à personne d'autre d'avoir «différents objectifs» avec l'objet.
AakashM

Réponses:

8

Je ne sais pas pourquoi vous devez conserver une liste de toutes les instances d'une classe.

Cela entraînerait une fuite de mémoire car ces objets ne seront jamais supprimés, car la liste les référencera toujours après aucune autre classe.

Mais si vous voulez vraiment suivre cette voie:

  1. Utilisez le modèle Factory. Une classe d'usine avec des méthodes qui instancient la classe et renvoient les objets. De cette façon, vous disposez d'un point centralisé pour contrôler les instanciations.
  2. Utilisez le modèle Singleton pour contenir une liste ou des listes contenant les instances.
  3. Faites en sorte que l'usine place chaque objet d'un certain type dans une liste après les avoir créés.

Soit dit en passant: les constructeurs sont hérités.

Tulains Córdova
la source
Vous pouvez bien sûr donner à l'usine une méthode de «suppression» qui supprime l'instance de sa liste d'instances suivies. Mais il n'y a aucun moyen de l'invoquer explicitement. Ou donnez à l'instance une méthode d'élimination qui déclenche la méthode d'élimination dans sa fabrique, qui présente le même inconvénient mais est légèrement plus susceptible d'être réellement appelée car elle est plus proche de l'utilisateur, plus visible.
jwenting
@jwenting Bien sûr, c'est un moyen. Mais cela créerait des dépendances moches et inutiles entre les classes et l'usine. Les classes ne doivent rien savoir de l'usine qui les crée.
Tulains Córdova
donc avoir l'usine garder une trace de ce qu'il crée, plutôt que l'objet dit à l'usine de l'enregistrer ...
jwenting
Un singleton techniquement détiendrait toutes les instances, je suppose. La seule instance.
Rig
3

Il convient de noter que les références faibles peuvent être utilisées en combinaison avec les autres solutions données pour permettre au garbage collector de disposer des objets suivis lorsqu'ils ne sont plus référencés ailleurs. Cela élimine les fuites de mémoire sans nécessiter de code ailleurs pour éliminer manuellement les objets, ou autrement prendre soin qu'ils soient suivis. Vous pouvez fournir un ReferenceQueue pour recevoir la notification des références aux objets qui ont été libérés.

J'ai pensé à un tableau ou à une collection statique, auquel à travers son constructeur, chaque nouvel objet créé serait ajouté. Cela ne fonctionnerait cependant pas avec les sous-classes, car les constructeurs ne sont pas hérités?

Les constructeurs des classes de base sont invoqués avant les constructeurs des classes dérivées. Chaque classe a au moins un constructeur et les constructeurs ne peuvent pas être remplacés.

user2313838
la source
2

Lors de la création de jeux, les gens veulent parfois une collection «autogérée» de chaque type d'objet de jeu.

Une implémentation ressemble à ceci:

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
    }
}

De cette manière, les méthodes manipulant la collection peuvent être déclarées statiques tandis que les méthodes non statiques manipulent une instance (updateAll vs update).

Bien que très bien pour des scénarios très simples, avec une complexité même modérée, il est généralement préférable de créer des classes de gestionnaire distinctes.

Kelly Thomas
la source
1
Vous pouvez directement écrire static ArrayList<ListeStatic> list = new ArrayList<ListeStatic>();et supprimer le statc {..}
cl-r
2
Dans le nom de la méthode Java commence par une lettre minuscule:uptdateAll(){..;}
cl-r
oups ... ça fait un moment que je n'ai pas diffusé ma java en public
Kelly Thomas
@KellyThomas Une voiture s'ajoutant à une liste, les supprimant d'elle-même. Cela ne semble pas naturel.
Tulains Córdova
1
@ CayetanoGonçalves en tant que champ statique, il s'agit d'une liste partagée par toutes les instances.
Kelly Thomas
2

Essayez de penser le contexte. Lorsque vous créez un objet, vous le faites dans un certain contexte. Par exemple, si votre jeu consiste à tirer sur des extraterrestres, votre application créera tout le temps de nouveaux objets extraterrestres. Ils seront affichés dans un champ appelé Espace (qui pourrait être la classe qui représente l'interface utilisateur principale).

Il est parfaitement naturel pour Space d'avoir une propriété nommée currentAliens, qui serait un tableau, auquel vous ajoutez chaque nouvel extraterrestre que vous créez. Si vous voulez permettre à votre utilisateur de déchirer le tissu de l'espace-temps et de détruire tous les extraterrestres à la fois, vous devez parcourir cette collection et détruire chaque objet.

Si vous vouliez avoir accès à cette collection d'étrangers à partir d'autres parties de votre application (par exemple, à partir d'une page Paramètres, où vous voudrez peut-être autoriser les utilisateurs à éliminer certains types d'étrangers d'un seul coup), votre contexte Paramètres serait doivent avoir accès à l'objet Space.

Wytze
la source