Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Parcourir toutes les instances d'une classe

12 réponses
Avatar
Vincent Courcelle
Bonjour,
je cherche le moyen de parcourir un à un toutes les instances d'une classe
en fait, ces objets représentes des objets réels déposés au sein de
différentes pièces (pas beaucoup d'objets et pas beaucoup de salles), quand
le joueur rentre dans la salle, je voudrais regarder chaque objet pour
savoir lesquels se trouvent dans cette salle.

une autre solution serait de créer une classe qui gère ces objets (via
HashMap etc...), mais ça ne me réjouit pas trop et j'ai pour contrainte
d'avoir le moins de classe possible
(Pour ceux qui connaissent, l'environnement de base est "the world of zuul")
merci :)

Vincent Courcelle
http://www.tubededentifrice.com et http://www.france-jeunes.net

10 réponses

1 2
Avatar
Xavier Tarrago
La technique de base, c'est de mettre une ArrayList de WeakReference en
static dans la classe :

public class MonObjet {
private static ArrayList tous = new ArrayList();

public MonObjet() {
tous.add(new WeakReference(this);
}

static ArrayList getObjectsDans(Piece p) {
ArrayList ret = new ArrayList();
Iterator it = tous.iterator();
while (it.hasNext()) {
WeakReference objref = (WeakReference)it.next();
if (objref.get() != null) {
MonObjet o = (MonObjet)objref.get();
if (o.estDans(p)) { // o est dans la piece
ret.add(o);
} else {
// La WeakReference est devenue null, l'objet n'existe
plus...menage!
it.remove();
}}}}}

Voilà, c'est pas testé ni même compilé, mais ça devrait le faire.
Penser à synchronizer si en multi thread.



"Vincent Courcelle" a écrit dans le message de
news:4164f12f$0$10259$
Bonjour,
je cherche le moyen de parcourir un à un toutes les instances d'une classe
en fait, ces objets représentes des objets réels déposés au sein de
différentes pièces (pas beaucoup d'objets et pas beaucoup de salles),
quand

le joueur rentre dans la salle, je voudrais regarder chaque objet pour
savoir lesquels se trouvent dans cette salle.

une autre solution serait de créer une classe qui gère ces objets (via
HashMap etc...), mais ça ne me réjouit pas trop et j'ai pour contrainte
d'avoir le moins de classe possible
(Pour ceux qui connaissent, l'environnement de base est "the world of
zuul")

merci :)

Vincent Courcelle
http://www.tubededentifrice.com et http://www.france-jeunes.net





Avatar
Laurent Bossavit
Vincent,

en fait, ces objets représentes des objets réels déposés au sein de
différentes pièces (pas beaucoup d'objets et pas beaucoup de salles), quand
le joueur rentre dans la salle, je voudrais regarder chaque objet pour
savoir lesquels se trouvent dans cette salle.


Qu'est-ce qui ne convient pas dans la solution normale, raisonnable, qui
consiste à gérer une association 1-N de Salle à Objet ?

public class Salle {
private List objetsContenus;
...etc...

Laurent
http://bossavit.com/thoughts/

Avatar
Vincent Courcelle
"Laurent Bossavit" a écrit dans le message de
news:
Vincent,

en fait, ces objets représentes des objets réels déposés au sein de
différentes pièces (pas beaucoup d'objets et pas beaucoup de salles),
quand
le joueur rentre dans la salle, je voudrais regarder chaque objet pour
savoir lesquels se trouvent dans cette salle.


Qu'est-ce qui ne convient pas dans la solution normale, raisonnable, qui
consiste à gérer une association 1-N de Salle à Objet ?

public class Salle {
private List objetsContenus;
...etc...


ça fait une duplication des données dans 2 endroits différents
sans compter le fait qu'un objet peut ici être dans plusieurs salles à la
fois (si jamais il y a une erreur de code par exemple)
dans ma logique, il est plus logique que "salle" soit un attribut de l'objet
en question, comme son poids, son nom, etc...
j'ai implémenté la méthode de la WeakReference donnée par Xavier, seulement
j'ai un probleme après avec le parcours de l'ArrayList (cf le pointeur dans
le code suivant, vers la fin)il me fait une erreur de compilation
"incompatibles types - found java.lang.Object but expected Item" : (le code
de la classe entière se trouve à la fin)


/**
* Retourne un ArrayList de tous les objets présents dans une salle.
*/
public static ArrayList getObjectsByRoom(Room room)
{
ArrayList ret=new ArrayList();
WeakReference obj;
Item thisItem;
Iterator i=items.iterator();
while(i.hasNext())
{
obj=(WeakReference)i.next();
if(obj.get()!=null)
{
thisItem=(Item)obj.get();
if(thisItem.getRoom()==room)
{ret.add(thisItem);}
}
else
{i.remove();}
}
return ret;
}

/**
* Retourne tous les objets présents dans la salle sous forme de chaîne.
*/
public static String getStringObjectsByRoom(Room room)
{
String returnString="";
boolean okúlse;
Item thisItem;
ArrayList liste=Item.getObjectsByRoom(room);
Iterator i=liste.iterator();
while(i.hasNext())
{
if(ok)
{returnString+=", ";}
thisItem=i.next(); <-------------------------------- ici
returnString+=thisItem.getName();
ok=true;
}
return returnString;
}







Classe complète :
import java.util.ArrayList;
import java.util.Arrays;
import java.lang.ref.WeakReference;
import java.util.Iterator;

/**
* Cette classe crée les objets présents dans les différentes salles.
*/
public class Item
{
private static ArrayList items=new ArrayList();
private String name;
private int weight;
private String description;
private Room room;
boolean isTaken;
boolean isUsed;

public Item(String name2,int weight2,String description2,Room room2)
{
items.add(new WeakReference(this));
name=name2;
weight=weight2;
descriptionÞscription2;
room=room2;
isTakenúlse;
isUsedúlse;
}

/**
* Prend l'objet en question.
*/
public void take()
{
isTaken=true;
}

/**
* Repose l'objet en question.
*/
public void unTake(Room room2)
{
if(isTaken && !isUsed)
{
isTakenúlse;
room=room2;
}
}

/**
* Utilise l'objet en question.
*/
public void use()
{
if(isTaken)
{isUsed=true;}
}

/**
* Retourne si l'objet a été pris ou non.
*/
public boolean isTaken()
{
return isTaken;
}

/**
* Retourne si l'objet a été utilisé ou non.
*/
public boolean isUsed()
{
return isUsed;
}

/**
* Retourne la salle de l'objet.
*/
public Room getRoom()
{
if(!isTaken && !isUsed)
{return room;}
return null;
}

/**
* Retourne la description de l'objet.
*/
public String getName()
{
return name;
}

/**
* Retourne la description de l'objet.
*/
public String getDescription()
{
return description;
}

/**
* Retourne un ArrayList de tous les objets présents dans une salle.
*/
public static ArrayList getObjectsByRoom(Room room)
{
ArrayList ret=new ArrayList();
WeakReference obj;
Item thisItem;
Iterator i=items.iterator();
while(i.hasNext())
{
obj=(WeakReference)i.next();
if(obj.get()!=null)
{
thisItem=(Item)obj.get();
if(thisItem.getRoom()==room)
{ret.add(thisItem);}
}
else
{i.remove();}
}
return ret;
}

/**
* Retourne tous les objets présents dans la salle sous forme de chaîne.
*/
public static String getStringObjectsByRoom(Room room)
{
String returnString="";
boolean okúlse;
Item thisItem;
ArrayList liste=Item.getObjectsByRoom(room);
Iterator i=liste.iterator();
while(i.hasNext())
{
if(ok)
{returnString+=", ";}
thisItem=i.next();
returnString+=thisItem.getName();
ok=true;
}
return returnString;
}
}






merci de votre aide ! je suis débutant en java (mais pas en programmation),
et c'est assez difficile d'assimiler la logique de "programmation orientée
objet"...


Avatar
ownowl

ça fait une duplication des données dans 2 endroits différents


non l'objet ne sera pas duppliqué. il y aura juste deux références sur le
même objet (une référence = 4 octets en mémoire (de mémoire))

sans compter le fait qu'un objet peut ici être dans plusieurs salles à la
fois (si jamais il y a une erreur de code par exemple)


d'autant plus.


Olivier

dans ma logique, il est plus logique que "salle" soit un attribut de
l'objet

en question, comme son poids, son nom, etc...
j'ai implémenté la méthode de la WeakReference donnée par Xavier,
seulement

j'ai un probleme après avec le parcours de l'ArrayList (cf le pointeur
dans

le code suivant, vers la fin)il me fait une erreur de compilation
"incompatibles types - found java.lang.Object but expected Item" : (le
code

de la classe entière se trouve à la fin)



Avatar
Franck
Salut,

Moi j'aurai tendance à te conseiller,
(si ton projet est amené à devenir relativement complexe)
d'avoir un modèle de données propre

ex dans ton cas :
un classe Joueur une classe Salle
et une classe Affectation qui gere des relations N/N

Ca te simplifiera la prog par la suite

Tchaw


--
Franck Lefebure
mailto:
Avatar
Vincent Courcelle
"Franck" a écrit dans le message
de news:
Salut,

Moi j'aurai tendance à te conseiller,
(si ton projet est amené à devenir relativement complexe)
d'avoir un modèle de données propre

ex dans ton cas :
un classe Joueur une classe Salle
et une classe Affectation qui gere des relations N/N

Ca te simplifiera la prog par la suite


c'est déjà le cas : pour le moment, j'ai :
une classe Patator (qui lance le jeu)
une classe Game
une classe Room
une classe Item
une classe Parser
une classe Command
une classe CommandWords

Avatar
Thomas Nguyen
On Thu, 07 Oct 2004 11:29:08 +0200, Vincent Courcelle wrote:
dans ma logique, il est plus logique que "salle" soit un attribut de l'objet
en question, comme son poids, son nom, etc...


Dans ma logique, j'aurais fait l'inverse. ;)
En fait, ça dépend de la manière dont tu utilises ton code et de tes
préférences personnelles.

Si tu "navigues" souvent dans le sens objet->salle (c-à-d que tu cherches
souvent à savoir dans quelle salle se trouve un objet donné), c'est plus
simple et plus rapide de mettre un attribut salle dans Objet. Si tu
navigues plus souvent dans l'autre sens (salle->objet), vaut mieux
conserver une liste des objets dans chaque salle.

Si tu navigues souvent dans les deux sens, fait les deux! (fait attention
à la cohérence des données, mais ton programme ne contient aucun bug,
n'est-ce pas? ;) )



j'ai implémenté la méthode de la WeakReference donnée par Xavier,
Je vois vraiment pas l'utilité d'utiliser des références faibles dans

ce cas. Des références normales me semblent aussi utiles, et plus
simples d'utilisation.
Xavier, avais-tu une raison particulière pour conseiller les
WeakReference?

j'ai un probleme après avec le parcours de l'ArrayList (cf le pointeur dans
le code suivant, vers la fin)il me fait une erreur de compilation
"incompatibles types - found java.lang.Object but expected Item" :


/**
* Retourne tous les objets présents dans la salle sous forme de chaîne.
*/
public static String getStringObjectsByRoom(Room room)
{
String returnString="";
boolean okúlse;
Item thisItem;
ArrayList liste=Item.getObjectsByRoom(room);
Iterator i=liste.iterator();
while(i.hasNext())
{
if(ok)
{returnString+=", ";}
thisItem=i.next(); <-------------------------------- ici
returnString+=thisItem.getName();
ok=true;
}
return returnString;
}


Faut ajouter un cast: thisItem=(Item)i.next();

Avatar
Olivier Thomann
Je vois vraiment pas l'utilité d'utiliser des références faibles dans
ce cas. Des références normales me semblent aussi utiles, et plus
simples d'utilisation.
Xavier, avais-tu une raison particulière pour conseiller les
WeakReference?
La raison que je vois est un problème de mémoire. Si tu n'utilises pas

des WeakReferences, tu riques d'avoir des problèmes de mémoire. Le gc ne
récupèrera pas les objets en question, si le système vient à manquer de
mémoire. Avec des WeakReferences, oui.
Xavier, j'ai raté quelque chose?
--
Olivier

Avatar
Vincent Cantin
La raison que je vois est un problème de mémoire. Si tu n'utilises pas
des WeakReferences, tu riques d'avoir des problèmes de mémoire. Le gc ne


heu ... c'est pas vrai si le programme ne contient pas de bugs. Le gc peut
collecter des objets meme dans des cycles de references (si le cycle entier
n'est plus atteignable a partir du programme).


récupèrera pas les objets en question, si le système vient à manquer de
mémoire. Avec des WeakReferences, oui.


Avatar
Xavier Tarrago
Si on garde une reference forte de la liste vers l'objet, il ne sera jamais
garbage-collecté. Dans ce cas, il faut gérer explicitement les destructions
des objets. Soit en utilisant les finalize (pas conseillé), soit en
architecturant le code de façon à ce que avant de perdre la dernière
référence à l'objet, on l'enlève de la liste.

Pour l'erreur, il suffit de caster l'objet. En efet, Iterator.get() retourne
un Object, mait toi, tu sais que cet Object est en réalité un Item. Donc
thisItem = (Item)iterator.get();

A la réflexion, j'ai donné une solution technique à une question technique.
Je voudrais quand même signaler que la solution qui consiste à intégrer une
relation au modèle et à la gérer par des listes est plus rationnelle.

"Thomas Nguyen" a écrit dans le message de
news:
On Thu, 07 Oct 2004 11:29:08 +0200, Vincent Courcelle wrote:
dans ma logique, il est plus logique que "salle" soit un attribut de
l'objet


en question, comme son poids, son nom, etc...


Dans ma logique, j'aurais fait l'inverse. ;)
En fait, ça dépend de la manière dont tu utilises ton code et de tes
préférences personnelles.

Si tu "navigues" souvent dans le sens objet->salle (c-à-d que tu cherches
souvent à savoir dans quelle salle se trouve un objet donné), c'est plus
simple et plus rapide de mettre un attribut salle dans Objet. Si tu
navigues plus souvent dans l'autre sens (salle->objet), vaut mieux
conserver une liste des objets dans chaque salle.

Si tu navigues souvent dans les deux sens, fait les deux! (fait attention
à la cohérence des données, mais ton programme ne contient aucun bug,
n'est-ce pas? ;) )



j'ai implémenté la méthode de la WeakReference donnée par Xavier,
Je vois vraiment pas l'utilité d'utiliser des références faibles dans

ce cas. Des références normales me semblent aussi utiles, et plus
simples d'utilisation.
Xavier, avais-tu une raison particulière pour conseiller les
WeakReference?

j'ai un probleme après avec le parcours de l'ArrayList (cf le pointeur
dans


le code suivant, vers la fin)il me fait une erreur de compilation
"incompatibles types - found java.lang.Object but expected Item" :


/**
* Retourne tous les objets présents dans la salle sous forme de
chaîne.


*/
public static String getStringObjectsByRoom(Room room)
{
String returnString="";
boolean okúlse;
Item thisItem;
ArrayList liste=Item.getObjectsByRoom(room);
Iterator i=liste.iterator();
while(i.hasNext())
{
if(ok)
{returnString+=", ";}
thisItem=i.next(); <-------------------------------- ici
returnString+=thisItem.getName();
ok=true;
}
return returnString;
}


Faut ajouter un cast: thisItem=(Item)i.next();





1 2