Précédent   Forum du club des développeurs et IT Pro > Java > Général Java > Langage
Langage Forum d'entraide sur le langage Java et autres langages pour la JVM : syntaxe, POO, conventions, API standard. Avant de poster -> FAQ Java
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 24/07/2007, 20h31   #1
Djakisback
Membre Expert
 
Avatar de Djakisback
 
Inscription : février 2005
Messages : 1 914
Détails du profil
Informations forums :
Inscription : février 2005
Messages : 1 914
Points : 1 840
Points : 1 840
Par défaut instanceof ou mauvais polymorphisme ?

Salut, j'ai un problème de base mais je ne comprends pas très bien le mécanisme à adopter, si quelqu'un pouvait me guider. J'ai par exemple, 3 classes :

Code :
1
2
3
4
5
6
7
8
 
public class SolidCircle extends Solid {
	public boolean collideWith(SolidCircle circle) {...}
}
 
public class SolidRectangle extends Solid {
	public boolean collideWith(SolidRectangle circle) {...}
}
Comment on fait pour récupérer et appeler la fonction adéquate dans le cas suivant, j'ai donc un vecteur qui contient des SolidRectangle et des SolidCircle :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public Vector movableSolids; // D'ailleurs il me semblait que Vector était pas trop optimisé pourtant c'est la seule structure que propose le CLDC 1.1 du J2ME
 
static public void computeCollisions() {
		for (int i = 0, solidsSize = PEngine.movableSolids.size(); i < solidsSize; i++) {
			Solid solid1 = ((Solid) (PEngine.movableSolids.elementAt(i)));
			for (int j = i + 1, solidsSize2 = PEngine.movableSolids.size(); j < solidsSize2; j++) {
				Solid solid2 = ((Solid) (PEngine.movableSolids.elementAt(j)));
				if (solid1.collideWith(solid2)) {
					PEngine.computeCollisionResponse(solid1, solid2);
				}
			}
		}
	}
 
	static public void computeCollisionResponse(SolidCircle circle1, SolidCircle circle2) {..}
 
	static public void computeCollisionResponse(SolidRectangle rectangle1, SolidRectangle rectangle2) {...}
J'ai pensé définir une méthode abstraite collideWith(Solid s) dans Solid mais ensuite il faut que j'en implémente une aussi dans SolidRectange et dans SolidCircle, ce qui n'a aucune utilité. Ma question est donc, comment appeler les bonnes méthodes collideWith et computeCollisionResponse, en fonction des types réels des instances, j'imagine qu'il y a moyen de faire ca sans instanceof ?
Merci d'avance ^^
Djakisback est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/07/2007, 09h48   #2
willoi
Membre Expert
 
Avatar de willoi
 
Développeur informatique
Inscription : décembre 2006
Messages : 1 355
Détails du profil
Informations personnelles :
Âge : 40
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : décembre 2006
Messages : 1 355
Points : 1 653
Points : 1 653
A mon avis cette ligne :

Code :
PEngine.computeCollisionResponse(solid1, solid2);
doit te donner une erreur de compilation.Car tu passe les parametres Solid, Solid a ta methode et celle ci n'existe pas.

Donc une solution peut etre d'utiliser instanceof puis un casting a la classe adequate.

Ou sinon implementer des methodes au niveau de tes classes SolidRectangle et SolidCircle.
Exemple :

Code :
solid1.computeCollisionResponse(solid2);
et creer une methode dans ta classe Solid :
Code :
computeCollisionResponse(Solid solid);
willoi est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/07/2007, 11h32   #3
freakfm
Nouveau Membre du Club
 
Inscription : juillet 2006
Messages : 113
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 113
Points : 33
Points : 33
à mon avis tu ajoute ces deux method dans tes class, et comme ça seulon le type des parametre java va savoire quel méthod utiliser.


Code :
1
2
3
4
5
6
7
8
9
10
 
public class SolidCircle extends Solid {
	public boolean collideWith(SolidCircle circle) {...}
        public boolean collideWith(SolidRectangle rectangle) {...}
}
 
public class SolidRectangle extends Solid {
	public boolean collideWith(SolidRectangle rectangle) {...}
        public boolean collideWith(SolidCircle circle) {...}
}
et aussi dans l'autre classe il faut ajouter les deux methodes:
Code :
1
2
3
 
static public void computeCollisionResponse(SolidCircle circle, SolidCircle rectangle) {..}
static public void computeCollisionResponse(SolidRectangle rectangle,  SolidCircle circle) {...}
ou à mon avis je dit de n'importe quoi. pour ce deusiéme probléme il faut peut etre faire comme ce qu' à dit "willoi"

en tous cas, tu doit développer deux methodes
Code :
computeCollisionResponse(Solid solid);
dans chaque class (circle et rectangle)

Code :
1
2
3
4
5
6
7
8
9
10
 
public class SolidCircle extends Solid {
	computeCollisionResponse(SolidCircle circle){...}
        computeCollisionResponse(SolidRectangle rectangle){...}
}
 
public class SolidRectangle extends Solid {
	computeCollisionResponse(SolidCircle circle){...}
        computeCollisionResponse(SolidRectangle rectangle){...}
}
freakfm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/07/2007, 15h23   #4
deltree
Membre confirmé
 
Inscription : mai 2007
Messages : 242
Détails du profil
Informations forums :
Inscription : mai 2007
Messages : 242
Points : 269
Points : 269
Bonjour,
je vois bien une solution simple:
Code :
1
2
3
4
5
6
7
8
9
10
11
 
public abstract class Solid {
	public final boolean collideWith(Solid solid) {
             if (solid instanceof SolidCircle) return collideWith((SolidCircle) solid);
             if (solid instanceof SolidRectangle) return collideWith((SolidRectangle) solid);
            return false;
        }
 
  protected abstract boolean collideWith(SolidCircle circle);
  protected abstract boolean collideWith(SolidRectangle rectangle);
}
parce que le polymorphisme ne s'applique pas sur la surcharge: il y aurais peut-être un moyen de faire du vrai polymorphisme en extrayant des méthodes dans des stratégies ou des Visitor, mais ça deviendrais over-compliqué.
deltree est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/07/2007, 15h41   #5
manblaizo
Membre éprouvé
 
Inscription : janvier 2006
Messages : 355
Détails du profil
Informations personnelles :
Localisation : Maroc

Informations forums :
Inscription : janvier 2006
Messages : 355
Points : 452
Points : 452
Bonjour,
Moi je préférerais plutôt ceci :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
public abstract class Solid {
    public abstract boolean collideWith(Solid solid);
}
 
public class SolidCircle extends Solid {
    public boolean collideWith(Solid solid) {
         if (! solid instanceof SolidCircle)
               return false;
 
        // sinon faire le traitement spécifique aux objets SolidCircle
       // et retourner "true" ou "false" selon le résultat du traitement
       SolidCircle circle = (SolidCircle)solid;
        ...
    }
}
 
public class SolidRectangle extends Solid {
    public boolean collideWith(Solid solid) {
         if (! solid instanceof SolidRectangle)
               return false;
 
        // sinon faire le traitement spécifique aux objets SolidRectangle
       // et retourner "true" ou "false" selon le résultat du traitement
       SolidRectangle rect = (SolidRectangle)solid;
        ...
    }
}
Ceci a l'avantage de conserver le caractère polymorphique de la méthode collideWith() et permet d'ajouter de nouvelle sous-classes de la classe Solid sans affecter cette dernière.
manblaizo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/07/2007, 15h53   #6
deltree
Membre confirmé
 
Inscription : mai 2007
Messages : 242
Détails du profil
Informations forums :
Inscription : mai 2007
Messages : 242
Points : 269
Points : 269
C'est vrai qu'on est obligé de modifier la classe abstraite pour chaque classe ajoutée, mais tu oublie un point
ce code est faux:
Code :
1
2
3
4
 
    public boolean collideWith(Solid solid) {
         if (! solid instanceof SolidRectangle)
               return false;
car un rectangle peut être en collision avec un cercle, et de même si on ajoute un SolidTriangle, il faudra revoir les classes cercle et rectangle pour gérer les collisions Triangle-cercle et triangle-rectangle.

pour bien faire il faudrait des instance d'opérateur binaire isCollision(Solid,Solid) , surchargés pour chaque type de couple Solid-Solid (un peu comme un Comparator), ce qui trop compliqué pour un cas simple comme celui-ci.
deltree est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/07/2007, 16h08   #7
manblaizo
Membre éprouvé
 
Inscription : janvier 2006
Messages : 355
Détails du profil
Informations personnelles :
Localisation : Maroc

Informations forums :
Inscription : janvier 2006
Messages : 355
Points : 452
Points : 452
Citation:
Envoyé par deltree
C'est vrai qu'on est obligé de modifier la classe abstraite pour chaque classe ajoutée, mais tu oublie un point
ce code est faux:
Code :
1
2
3
4
 
    public boolean collideWith(Solid solid) {
         if (! solid instanceof SolidRectangle)
               return false;
car un rectangle peut être en collision avec un cercle, et de même si on ajoute un SolidTriangle, il faudra revoir les classes cercle et rectangle pour gérer les collisions Triangle-cercle et triangle-rectangle.

pour bien faire il faudrait des instance d'opérateur binaire isCollision(Solid,Solid) , surchargés pour chaque type de couple Solid-Solid (un peu comme un Comparator), ce qui trop compliqué pour un cas simple comme celui-ci.
Pourant à bien lire son premier post, il cherche plutôt à comparer des SolidCircle entre eux, des SolidRectangle entre eux, et ainsi de suite. Pour pouvoir appeler la méthode computeCollisionResponse() par exemple, les deux solid doivent être de même sous-classe. Ce qui suppose qu'il ne considère que les collisions d'objets de même type. Sinon il faudrait reconsidérer la notion de collision entre objets Solid, quel que soit le sous-type et dans ce cas il faudrait peut-être introduire une variable membre dans la classe Solid (rectangleShape par exemple) qui serait partagée par toutes les sous-classes et définirait donc ce qu'est une collision entre un cercle et un rectangle.
Tout est question de définition des concepts.
manblaizo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/07/2007, 16h46   #8
deltree
Membre confirmé
 
Inscription : mai 2007
Messages : 242
Détails du profil
Informations forums :
Inscription : mai 2007
Messages : 242
Points : 269
Points : 269
D'accord, moi je l'avais interprété comme étant de la collision d'objets géométrique
de toutes façon, nos méthodes se rejoignent sur le fait qu'il faut appeler les objets par une seule méthode d'entrée publique "collideWith(Solid)" que tu implémente dans les sous classes pour plus d'évolutivité, et que moi je préfère implémenter dans la superclasse pour mieux "vérouiller" le code si jamais toutes les classes sont interdépendantes. Ce qui nous oblige à utiliser le instanceOf: dans les 2 cas, on est obligé.
deltree est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/07/2007, 17h48   #9
Djakisback
Membre Expert
 
Avatar de Djakisback
 
Inscription : février 2005
Messages : 1 914
Détails du profil
Informations forums :
Inscription : février 2005
Messages : 1 914
Points : 1 840
Points : 1 840
Salut,
et merci beaucoup pour vos réponses
Mon but est en effet de pouvoir tester toutes les combinaisons possibles.
J'aimerais vraiment éviter d'utiliser instanceof si c'est possible car ca me semble un peu lourd.
Pour le collideWith je crois je vais finalement passer par une méthode de la classe statique PEngine, ca m'évitera des doublons de code, ca pourrait donner un truc du style :

Code :
1
2
3
4
5
 
--- PEngine ----
static boolean areCollide(SolidCircle s1, SolidCircle s2)
static boolean areCollide(SolidRectangle s1, SolidRectangle s2)
static boolean areCollide(SolidCircle s1, SolidRectangle s2)
Mais finalement mon gros problème se situe à la récupération des objets depuis les listes. Je me demande si il vaudrait mieux pas que je sépare tout simplement les formes :

Code :
1
2
3
static Vector movableSolidCircles;
static Vector movableSolidsRectangles;
static Vector movableSolidsPolygons;
Comme ca je serai sûr des types réels à la récupération. Par contre ca risque de compliquer les boucles de parcours mais je pense que ca sera toujours mieux que des instanceof.

En tout cas merci encore pour vos avis et suggestions ^^ (passés et futurs ;P)
Djakisback est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/07/2007, 19h25   #10
deltree
Membre confirmé
 
Inscription : mai 2007
Messages : 242
Détails du profil
Informations forums :
Inscription : mai 2007
Messages : 242
Points : 269
Points : 269
Par défaut Djakisback ... is back :D

C'est une bonne idée en terme de conception de vouloir éviter l'instanceOf, et bien souvent ça montre que le polymorphisme est mal employé, en particulier quand le "message" i.e. la méthode s'adresse à un seul objet polymorphe.

idée de départ de polymorphisme
là on a 2 objets polymorphe, et c'est le drame, on atteind la limite du polymorphisme Java, et comme je tentait de l'évoquer, on pourrait tenter de passer outre en Définissant un type supplémentaire sous classé pour chaque couple de sous-classe de Solid-Solid:
Code :
1
2
3
4
 
interface Collision{
public boolean isCollided(Solid s1, Solid s2);
}
Cette classe définissant la collision vue comme un opérateur binaire de l'ensemble des Solid (edit: je me suis un peu emballé)

C'est un sujet intéressant au niveau conceptuel, même si au niveau réalisation c'est carrément overkill( surtout si tu est en JME comme j'au cru comprendre)

ta solution basée sur du static, ou alors sur la super classe
Pour ce qui est de l'utilisation des static, pour moi la programmation objet doit toujours être logique, et donc dans notre cas l'objet doit pouvoir porter ses méthodes, quitte à rediriger sur des classes "utilitaires" constituées de méthodes statiques.
Autre solution: tu ne duplique rien si tu met tout ton code dans la classe abstraite (mais on se demande alors l'utilité de sous-classer)

Conception et implémentation d'un polymorphisme "binaire" sans instanceOf
pour revenir au cas d'école de sous classement de Collision, j'improvise à l'instant ma solution:
Dans une Factory destinée à instancier les Solid, on peut également instancier toutes les possibilités de Collision, et les affecter à 2 tableau collisionCandidates1 et collisionCandidates2 communs à tous les objets Solid d'un type... tout ça dans le seul but d'exploiter le polymorphisme de l'objet Solid sur 2 méthodes polymorphe me rendant les opérateurs binaires possibles (les Candidate) pourquoi 2?
pour ensuite extraire l'intersection des 2 ensembles, et ne retenir que l'opérateur binaire possible. C'est un peu long, mais on n'a utilisé aucune instanceOf, et je ne vois pas plus imple pour l'instant. A défaut d'antériorité sur l'algo, appelons ça le "Deltree Overkill Binary Candidate Pattern" et voici le code

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 
//passons nous de la Factory pour l'instant
class RectRectCollision implements Collision{...}
class RectCircleCollision implements Collision{...}
class CircleRectCollision implements Collision{...}
class CircleCircleCollision implements Collision{...}
 
class Solid{
// les collisions dont le 1er arguement est de mon type
protected abstract void getCollisionCandidates1();
// les collisions dont le  2ème argument est de mon type
protected abstract voièmed getCollisionCandidates2();
 
public boolean isCollided(Solid s2){
  return getCollision(this,s2).isCollided(this,s2);
}
 
// simplement renvoie les élements appartenant aux 2 listes
private boolean listIntersection(List l1, List l2){
  // boucler sur l1
  for (int i ....){
    if l2.contains(l1.get(i))
	 return l1.get(i)
  }
 
}
 
public Collision getCollision(){
  return listIntersection(s1.getCollisionCandidates1(), s2.getCollisionCandidates2() );
}
}
 
public SolidCircle extends Solid{
  public static final List candidates1 = new ArrayList(new Object[]{
   new CircleCircleCollision(),
   new CircleRectCollision()});
  public static final List candidates2 = new ArrayList(new Object[]{
   new CircleCircleCollision(),
   new RectCircleCollision()});
  // le polymorphisme enfin !!
  getCollisionCandidates1(){ return candidates1;
 }
  getCollisionCandidates2(){ return candidates2;
 }
}
j'avoue que je me suis un peu amusé, à l'occasion, je testerait ça sur d'autre type d'opérateur binaire, avec notamment la gestion de commutativité.
deltree est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/07/2007, 19h46   #11
manblaizo
Membre éprouvé
 
Inscription : janvier 2006
Messages : 355
Détails du profil
Informations personnelles :
Localisation : Maroc

Informations forums :
Inscription : janvier 2006
Messages : 355
Points : 452
Points : 452
Moi je n'ai toujours pas compris cette notion de collision, comment cela se traduit-elle ? Par exemple, qu'est-ce qui doit être vérifié pour conclure qu'un solidCircle est en collision avec un solidRectangle ? Il doit certainement y en avoir des variables membre qui sont comparées, mais lesquelles ?
manblaizo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/07/2007, 09h46   #12
deltree
Membre confirmé
 
Inscription : mai 2007
Messages : 242
Détails du profil
Informations forums :
Inscription : mai 2007
Messages : 242
Points : 269
Points : 269
Les collisions c'est la gestion des objets dans un jeu 3D par exemple: 2 objet ne peuvent pas se trouver au même endroit sinon ils sont en collision: si c'est un mur on n'avance plus etc.

géométriquement ça se traduit par le fait que 2 objets sont en collision s'il existe un point (x,y) qui appartient aux 2 figures géométriques (ou (x,y,z) en 3D ). Dans la pratique, l'algo va rechercher l'intersection entre les figures gémétrique.
deltree est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/07/2007, 12h56   #13
Djakisback
Membre Expert
 
Avatar de Djakisback
 
Inscription : février 2005
Messages : 1 914
Détails du profil
Informations forums :
Inscription : février 2005
Messages : 1 914
Points : 1 840
Points : 1 840
Effectivement, l'idée du DOBCP est intéressante
Djakisback est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/07/2007, 15h34   #14
deltree
Membre confirmé
 
Inscription : mai 2007
Messages : 242
Détails du profil
Informations forums :
Inscription : mai 2007
Messages : 242
Points : 269
Points : 269

ouaip, à défaut, un pattern BCP si ça fait un peu mégalo le nom de pseudo dans un pattern.

as-tu essayé? ou est-ce que finalement tu n'avais pas besoin des instanceOf avec des méthodes static?
deltree est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/07/2007, 16h29   #15
bulbo
Rédacteur
 
Avatar de bulbo
 
Homme
Consultant informatique
Inscription : février 2004
Messages : 1 192
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 40
Localisation : France

Informations professionnelles :
Activité : Consultant informatique
Secteur : Finance

Informations forums :
Inscription : février 2004
Messages : 1 192
Points : 1 905
Points : 1 905
Pourquoi ne pas essayer une approche du type Visitor comme mentionne plus haut ?
Ca parait la solution adequate, exemple avec du code:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 
public abstract class Solid
{
 
  private String _name;
 
  /** Creates a new instance of Solid */
  public Solid(String aName)
  {
    _name = aName;
  }
 
  public abstract boolean collideWith(Solid aSolid);
 
  public boolean collideWith(SolidCircle aSolid)
  {
    return false;
  }
 
  public boolean collideWith(SolidRectangle aSolid)
  {
    return false;
  }
 
  public String toString()
  {
    return _name;
  }
 
  public static void main(String args[])
  {
    try
    {
      Solid a = new SolidCircle("A");
      Solid b = new SolidRectangle("B");
 
      a.collideWith(b);
      b.collideWith(a);
      b.collideWith(b);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }
}
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
public class SolidCircle extends Solid
{
 
  /** Creates a new instance of SolidCircle */
  public SolidCircle(String aName)
  {
    super(aName);
  }
 
  public boolean collideWith(Solid aSolid)
  {
    return aSolid.collideWith(this);
  }
 
  public boolean collideWith(SolidCircle aSolid)
  {
    return PEngine.computeCircleCircleCollision(this, aSolid);
  }
 
  public boolean collideWith(SolidRectangle aSolid)
  {
    return PEngine.computeCircleRectangleCollision(this, aSolid);
  }  
}
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class SolidRectangle extends Solid
{
 
  /** Creates a new instance of SolidRectangle */
  public SolidRectangle(String aName)
  {
    super(aName);
  }
 
  public boolean collideWith(Solid aSolid)
  {
    return aSolid.collideWith(this);
  }
 
  public boolean collideWith(SolidCircle aSolid)
  {
    return PEngine.computeCircleRectangleCollision(aSolid, this);
  }
 
  public boolean collideWith(SolidRectangle aSolid)
  {
    return PEngine.computeRectangleRectangleCollision(this, aSolid);
  }
 
}
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class PEngine
{
 
  public static boolean computeCircleCircleCollision(SolidCircle circle1, SolidCircle circle2)
  {
    System.out.println("Collision Circle " + circle1 + " with Circle " + circle2);
    return true;
  }
 
  public static boolean computeCircleRectangleCollision(SolidCircle circle, SolidRectangle rect)
  {
    System.out.println("Collision Circle " + circle + " with Rectangle " + rect);
    return true;
  }
 
  public static boolean computeRectangleRectangleCollision(SolidRectangle rect1, SolidRectangle rect2)
  {
    System.out.println("Collision Rectangle " + rect1 + " with Rectangle " + rect2);
    return true;
  }
 
}
Avec ce code pas besoin d'instanceOf, le seul overhead est de devoir implementer la methode abstraite collideWith (toujours le meme code de toute facon donc pas tres dur a faire)
Et d'implementer les collideWith avec en signature les solides possible au niveau collision, pour l'exemple j'ai utilise une classe PEngine contenant en static le code des collisions (et pas besoin de 36 signatures pour 2 memes types comme tu peux le voir)

Si une collision n'est pas implementee dans la classe collideWith retournera false.

En cas d'ajout d'un solide une nouvelle methode collideWith doit etre ajoutee a Solid et un collideWith doit etre defini dans chaque classe pouvant entrer en collision avec le nouveau solide.

C'est lourd mais c'est l'inconvenient du typage dynamique a la mode java, pas le choix.

Bulbo
__________________
[Java] [NetBeans] [CVS]
La FAQ Java
Merci de ne pas me poser de questions techniques par MP.
!! J'aurais voulu être une conserve !!
bulbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/07/2007, 12h50   #16
Djakisback
Membre Expert
 
Avatar de Djakisback
 
Inscription : février 2005
Messages : 1 914
Détails du profil
Informations forums :
Inscription : février 2005
Messages : 1 914
Points : 1 840
Points : 1 840
Salut,
merci pour cette nouvelle réponse ^^

deltree << non, j'ai pas tenté

Finalement j'ai tout résolu en statique, ca m'a semblé le moins lourd et le plus maintenable, donc pas de Solid.collideWith mais plusieurs fonctions statiques dans PEngine. En cas d'ajout d'une classe de solide, seule PEngine est modifiée.
Je suis passé par des interfaces étant donné que l'héritage multiple n'existe pas :/, car en réalité j'ai (Solid<-SolidRectangle; Solid<-MovableSolid<-MovableSolidRectangle). J'avais donc besoin d'une interface ISolidRectangle. J'ai donc des méthodes dans PEngine prenant en arguments des interfaces :

Code :
1
2
3
static public boolean areCollide(ISolidRectangle solid1, ISolidRectangle solid2)
static public boolean areCollide(ISolidRectangle solid1, ISolidCircle solid2)
etc.
Et les réponses de collision prenant en compte des types de solides. Les réponses ne sont pas les mêmes entre 2 MovableSolid et 2 Solid :

Code :
1
2
3
4
 
	static public void computeCollisionResponse(MovableSolidRectangle rectangle1, MovableSolidRectangle rectangle2)
	static public void computeCollisionResponse(MovableSolidRectangle rectangle1, SolidRectangle rectangle2)
etc.
J'ai oublié de préciser que ceci n'est possible qu'en stockant les objets dans des listes séparés :

Code :
1
2
3
4
Vector movableSolidsRectangles;
Vector movableSolidsCircles;
Vector solidsRectangles;
etc.
Djakisback est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/07/2007, 13h00   #17
deltree
Membre confirmé
 
Inscription : mai 2007
Messages : 242
Détails du profil
Informations forums :
Inscription : mai 2007
Messages : 242
Points : 269
Points : 269

J'ai réfléchi pendant 1/4 heure pour comprendre comment ça marche, pourtant je connait le pattern Visitor, mais je butait sur la méthode collideWith implémentée dans chaque classe pour faire un appel à la méthode surchargée et typée.

Bref, c'est un bon compromis simplicité/modularité.

ça ne vaudrais pas le coup de faire un JSR (?) à Sun pour qu'on puisse utiliser dynamiquement une surcharge au lieu de laisser tous les développeur de la Terre se faire des noeuds aux cerveaux là-dessus?
deltree est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/07/2007, 13h03   #18
Djakisback
Membre Expert
 
Avatar de Djakisback
 
Inscription : février 2005
Messages : 1 914
Détails du profil
Informations forums :
Inscription : février 2005
Messages : 1 914
Points : 1 840
Points : 1 840
bulbo, avec ce code j'aurai quand même le problème que j'avais au départ pour le parcours de boucle non ? à savoir que les bonnes méthodes ne seront pas appelées en fonction des types réels des instances, étant donné que je suis obligé de caster pour la récupération :

Code :
1
2
3
4
5
6
7
8
9
10
11
static public void computeCollisions() {
		for (int i = 0, solidsSize = PEngine.movableSolids.size(); i < solidsSize; i++) {
			Solid solid1 = ((Solid) (PEngine.movableSolids.elementAt(i)));
			for (int j = i + 1, solidsSize2 = PEngine.movableSolids.size(); j < solidsSize2; j++) {
				Solid solid2 = ((Solid) (PEngine.movableSolids.elementAt(j)));
				if (solid1.collideWith(solid2)) { // Ici, ce ne sera pas la bonne méthode appelée il me semble
					PEngine.computeCollisionResponse(solid1, solid2);
				}
			}
		}
	}
si oui où est l'intérêt ?
(J'ai du louper un truc, je réexamine le code ^^)
Djakisback est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/07/2007, 13h06   #19
bulbo
Rédacteur
 
Avatar de bulbo
 
Homme
Consultant informatique
Inscription : février 2004
Messages : 1 192
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 40
Localisation : France

Informations professionnelles :
Activité : Consultant informatique
Secteur : Finance

Informations forums :
Inscription : février 2004
Messages : 1 192
Points : 1 905
Points : 1 905
Citation:
Envoyé par Djakisback
bulbo, avec ce code j'aurai quand même le problème que j'avais au départ pour le parcours de boucle non ? à savoir que les bonnes méthodes ne seront pas appelées en fonction des types réels des instances, étant donné que je suis obligé de caster pour la récupération :

Code :
1
2
3
4
5
6
7
8
9
10
11
static public void computeCollisions() {
		for (int i = 0, solidsSize = PEngine.movableSolids.size(); i < solidsSize; i++) {
			Solid solid1 = ((Solid) (PEngine.movableSolids.elementAt(i)));
			for (int j = i + 1, solidsSize2 = PEngine.movableSolids.size(); j < solidsSize2; j++) {
				Solid solid2 = ((Solid) (PEngine.movableSolids.elementAt(j)));
				if (solid1.collideWith(solid2)) { // Ici, ce ne sera pas la bonne méthode appelée il me semble
					PEngine.computeCollisionResponse(solid1, solid2);
				}
			}
		}
	}
si oui où est l'intérêt ?
(J'ai dû louper un truc, je réexamine le code ^^)
Essaye le code tel quel, l'exemple est 'parlant' si je puis dire, regarde les tests qui doivent etre fait (sans cast ni instanceOf) et regarde ce qui est execute.

C'est un poil plus d'implementation que ce que tu fais mais tu tires vraiment avantage de la liaison dynamique et pas besoin de listes separees.

Bulbo
__________________
[Java] [NetBeans] [CVS]
La FAQ Java
Merci de ne pas me poser de questions techniques par MP.
!! J'aurais voulu être une conserve !!
bulbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/07/2007, 13h31   #20
Djakisback
Membre Expert
 
Avatar de Djakisback
 
Inscription : février 2005
Messages : 1 914
Détails du profil
Informations forums :
Inscription : février 2005
Messages : 1 914
Points : 1 840
Points : 1 840
Effectivement j'avais vraiment lu à l'arrache
Cette solution est très intéressante.
Je vais réfléchir à ce que je vais faire (et peut-être tester les 2 soluces en termes de vitesse, ca ajoute quand même quelques pointeurs pour chaque instance d'objet, je suis pas un rapace mais bon ), merci encore ^^
Djakisback est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 02h19.


 
 
 
 
Partenaires

Hébergement Web