IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Redéfinition puis surcharge


Sujet :

Java

  1. #1
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 442
    Par défaut Redéfinition puis surcharge
    Bonjour,

    J'ai un problème pour lequel je n'arrive pas à mettre en forme une solution propre.

    J'ai une classe abstraite mère "ComposantGraphique". Des classes filles "Point", "Droite", "Segment", etc.

    J'ai une fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public abstract class ComposantGraphique {
        public abstract LinkedList<Point> pointDIntersection(ComposantGraphique cg);
    }
    En en gros, je dois renvoyer les intersections d'un composant avec un autre.

    Dans chaque classe fille, je voudrais donc pouvoir décliner les cas :
    pointDIntersection(Droite d)
    pointDIntersection(Segment AB)
    etc

    Comment dois-je faire si je veux éviter de passer par une liste de instanceof dans chaque classe fille :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class Droite extends ComposantGraphique {
        public LinkedList<Point> pointDIntersection(ComposantGraphique cg) {
            if(cg instanceof Droite {pointDIntersection((Droite)cg);}
            if(cg instanceof Segment {pointDIntersection((Segment)cg);}
            ...
        }
    }

  2. #2
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2011
    Messages
    262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 262
    Par défaut
    salut je me pose des questions sur ton exemple.

    lorsque tu as redéfini la méthode pointDIntersection , tu as retiré le type de retour. pourquoi??

    la deuxième question : dans ta classe concrété Droite dans sa méthode pointDIntersection
    tu appelle encore une fois la méme méthode pointDIntersection récursivement , c'est pour quelle intérêt?

  3. #3
    Membre habitué
    Inscrit en
    Février 2013
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Février 2013
    Messages : 11
    Par défaut
    Tout d'abord tu dois avoir un objet à retourner !

  4. #4
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 442
    Par défaut
    C'était un oubli lors de la rédaction du post. Désolé.

    Ca ne change pas le problème.

  5. #5
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Ce que je ferais, moi, c'est d'abord une interface IntersectionCalculator, du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    interface IntersectionCalculator<A extends ComposantGraphique, B extends ComposantGraphique> {
     
      LinkedList<Point> pointDIntersection(A a, B b);
     
    }
    Ensuite il va falloir :

    - En faire une implémentation pour chaque combinaison possible.

    - Trouver comment appeler la bonne implémentation sans faire de suites de instanceof.
    Pour ça je définirais une Map<Set<Class<? extends ComposantGraphique>>, IntersectionCalculator<? extends ComposantGraphique, ? extends ComposantGraphique>>.

    Dans laquelle, pour chaque combinaison possible, je crée un HashSet contenant les deux classes correspondantes, et j'y associe le IntersectionCalculator correspondant.

    Ainsi donc, quand je veux faire un calcul d'intersection entre deux objets, je construis un HashSet qui contient les classes de ces deux objets (si les objets sont de même classe, le HashSet ne contiendra donc qu'une classe, ce qui n'est pas un problème,) et à l'aide de la Map j'obtiens l'implémentation correspondante. Reste plus qu'à l'appeler sur mes deux objets.

    Il y a quelques problèmes de cohérence de type générique, et pour déterminer dans quel ordre passer les deux paramètres. Du coup, la Map elle-même devrait être chapeautée par un genre de Manager qui ignorera les génériques dans une partie de son code, et qui regardera par réflectivité quel est le type du premier paramètre, celui du second, et donc dans quel ordre passer l'un et l'autre.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par Sharcoux Voir le message
    Dans chaque classe fille, je voudrais donc pouvoir décliner les cas :
    pointDIntersection(Droite d)
    pointDIntersection(Segment AB)
    Si tu n'as pas défini ces méthodes dans l'interface, pour l'utilisateur, elles n'existent pas. Donc définir toutes ces méthodes dans l'interface, mais c'est moche.

    Sans compter le double emploi. En effet, tu va écrire du code pour l'intersection avec un plan dans Droite, puis tu va écrire le même code à l'envers pour l'intersection avec un Droit dans la classe Plan :/


    En sus, tu commence à avoir le problème que chaque classe fille doit connaitre toutes les autres classes filles possible, et tu complexifie ton problème :/ Comme gérer un nouveau type?

    Le mieux, selon moi, serait une classe centrale, indépendante, capable de gérer les différents cas, avec des trucs comme


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public List<Point> intersection(Droite d, Plan p){
    //...
    }
    public List<Point> intersection(Plan p, Droite d) {return intersection (d,p);}
    //....
    etc


    Il n'y a de toutes façons pas de solution générique, sinon il y a longtemps que la méthode equals de Object serait revue pour être plus simple à code

  7. #7
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 442
    Par défaut
    Merci pour vos réponses.

    Je voulais tenter quelque chose, mais j'aimerais avoir votre avis :

    en gros, je pars du principe que chaque Composant s'ajoute a une sorte de "pool" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    //première classe composant
    class Droite ... {
        ...
        intersection(Droite)...
    }
     
    //deuxième
    class Segment ... {
        ...
        intersection(Droite)...
        intersection(Segment)...
    }
     
    //nième
    class xxx {
        ...
        intersection(Droite)...
        intersection(Segment)...
        ...
        intersection(xxx)...
    }
    Enfin, dans chaque class, la méthode pointDIntersection(ComposantGraphique cg) essaye intersection(cg) ou renvoie cg.pointDIntersection(this)

    Je pars donc du principe que :

    - chaque nouveau Composant doit prendre en compte les intersections avec les autres types déjà existants
    - De cette façon, si cg1.intersection(cg2) n'existe pas, alors cg2.intersection(cg1) existe forcément.

    Qu'en pensez-vous ?

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Bien que ce soit correct et jouable, je n'aime en général pas l'idée du "dernier arrivé est responsable de tous les autres", ça pose vite des problèmes quand le code évolue:

    -> si un programmeur oublie un des cas
    -> quand deux programmeurs se mettent à travailler en même temps, qui est responsable de quoi?. J'ai tendance à préférer pour ça les classes centrales. Mais elles ont aussi leurs emmerdes quand on commence à jouer avec plusieurs librairies qui fourniraient des formes plus tordue, comme une librairie "patatoides.jar", une autre "moebius.jar" etc

  9. #9
    Membre averti
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Par défaut
    Citation Envoyé par Sharcoux Voir le message
    Comment dois-je faire si je veux éviter de passer par une liste de instanceof dans chaque classe fille :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class Droite extends ComposantGraphique {
        public LinkedList<Point> pointDIntersection(ComposantGraphique cg) {
            if(cg instanceof Droite {pointDIntersection((Droite)cg);}
            if(cg instanceof Segment {pointDIntersection((Segment)cg);}
            ...
        }
    }
    Il suffit d'utiliser le polymorphisme de java (cf post upcasting) .Il s'agit juste d'un problème de conception de classe.
    En faisant dériver les classes filles Droite,Segment d'un même classe abstraite ou d'une interface tu te dispenses justement de tester le type : lors de l’exécution d'une méthode il n'est plus nécessaire de tester la classe de l'objet afin de savoir comment downcaster.

  10. #10
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par WebSteph0 Voir le message
    Il suffit d'utiliser le polymorphisme de java (cf post upcasting) .Il s'agit juste d'un problème de conception de classe.
    En faisant dériver les classes filles Droite,Segment d'un même classe abstraite ou d'une interface tu te dispenses justement de tester le type : lors de l’exécution d'une méthode il n'est plus nécessaire de tester la classe de l'objet afin de savoir comment downcaster.
    Ben non dans le cas présent ça marche pas : l'objet en cours sait de quelle classe il est, mais ça résout pas le problème pour l'objet avec lequel il doit calculer son intersection.
    Au bout du compte c'est logique : il faut une implémentation du calcul pour chaque combinaison possible. S'il n'y a que deux classes ça fait trois combinaisons, donc trois implémentations nécessaire. Le polymorphisme ne permet qu'une implémentation par classe, ce qui en fait deux. Il manque la troisième. Mathématiquement il est clair que ça ne peut pas marcher.
    C'est un problème récurrent quand on doit associer des objets de classes différentes et que chaque combinaison de classes a son propre algorithme.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    Membre averti
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Par défaut
    Je n'avais pas vu de problème combinatoire dans la question des instanceof.
    Mais peux tu détailler une solution avec 2 classes ? (pour mieux voir le souci d'association de classes différentes...) merci

  12. #12
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    Ton architecture a un problème puisque pointDIntersection renvoie des points alors que mathématiquement, ca peut etre infini (par exemple dans le cas d'une droite et d'un segment/une autre droite confondus). Si c'est normal, on peut supposer que tu te places dans un espace discret (c'est à dire non continu) et dans une fenetre finie.
    Dans ce cas, pour avoir une solution générique, on pourrait imaginer créer pour chaque ComposantGraphique une fonction int[] pointsY(int x) qui renvoie les valeurs de y pour chaque point x (en supposant 2 dimensions). Ainsi, il serait plus simple de vérifier les points d'intersection.

    Encore une fois, ca suppose un problème très réducteur par rapport à ce qu'il pourrait etre mathématiquement mais ca peut peut etre te suffire...

  13. #13
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par WebSteph0 Voir le message
    Mais peux tu détailler une solution avec 2 classes ? (pour mieux voir le souci d'association de classes différentes...) merci
    Entendons-nous bien : c'est abominablement compliqué. Pour un nombre de classes raisonnables, je me baserais sur des chaînes de instanceof.
    Mais en cas d'explosion du nombre de classes, donc des instanceof, je ferais quelque chose de ce genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    abstract class ComposantGraphique {
      public LinkedList<Point> pointDIntersection(ComposantGraphique cg) {
        return ManagerIntersections.pointDIntersection(this, cg);
      }
    }
     
    class Cercle extends ComposantGraphique {
      public Point getCentre() {
        return null; //*osef
      }
      public int getRayon() {
        return 0; // osef
      }
    }
     
    class Ligne extends ComposantGraphique {
      public Point getPoint1() {
        return null; //*osef
      }
      public Point getPoint2() {
        return null; // osef
      }
    }
     
    interface CalculateurIntersection<A extends ComposantGraphique, B extends ComposantGraphique> {
      LinkedList<Point> pointDIntersection(A a, B b);
    }
     
    class IntersectionCercles implements CalculateurIntersection<Cercle, Cercle> {
      @Override
      public LinkedList<Point> pointDIntersection(Cercle a, Cercle b) {
        System.out.println("Calcul savant à partir des centres et rayons des cercles");
        return null;
      }
    }
     
    class IntersectionLignes implements CalculateurIntersection<Ligne, Ligne> {
      @Override
      public LinkedList<Point> pointDIntersection(Ligne a, Ligne b) {
        System.out.println("Calcul savant à partir des bouts des lignes");
        return null;
      }
    }
     
    class IntersectionCercleLigne implements CalculateurIntersection<Cercle, Ligne> {
      @Override
      public LinkedList<Point> pointDIntersection(Cercle cercle, Ligne ligne) {
      System.out.println("Calcul savant à partir du centre et du rayon du cercle, et des bouts de la ligne");
      return null;
      }
    }
     
    class ManagerIntersections {
      private static final Map<Set<Class<?>>, CalculateurIntersection<?, ?>> map = new HashMap<>();
     
      private static <A extends ComposantGraphique, B extends ComposantGraphique>
        void enregistrerCalculateur(CalculateurIntersection<A, B> calculateur, Class<A> aClass, Class<B> bClass) {
     
        Set<Class<?>> set = new HashSet<>();
        set.add(aClass);
        set.add(bClass);
        map.put(set, calculateur);
      }
     
      static {
        enregistrerCalculateur(new IntersectionCercles(), Cercle.class, Cercle.class);
        enregistrerCalculateur(new IntersectionLignes(), Ligne.class, Ligne.class);
        enregistrerCalculateur(new IntersectionCercleLigne(), Cercle.class, Ligne.class);
      }
     
      public static LinkedList<Point>
        pointDIntersection(ComposantGraphique a, ComposantGraphique b) {
     
        // récupérer le calculateur adéquat
        Set<Class<?>> set = new HashSet<>();
        Class<?> aClass = a.getClass();
        Class<?> bClass = b.getClass();
        set.add(aClass);
        set.add(bClass);
        @SuppressWarnings("unchecked")
        CalculateurIntersection<ComposantGraphique, ComposantGraphique> calculateur =
          (CalculateurIntersection<ComposantGraphique, ComposantGraphique>)map.get(set);
     
        // Gérer le cas où il n'a pas été enregistré
        if(calculateur == null) {
          throw new IllegalArgumentException("Combinaison de composants inconnue");
        }
     
        // Déterminer dans quel ordre appeler les paramètres
        ParameterizedType calculateurType = (ParameterizedType)calculateur.getClass().getGenericInterfaces()[0];
        Type firstType = calculateurType.getActualTypeArguments()[0];
        if(firstType == aClass) {
          // appeler avec le paramètre a en premier
          return calculateur.pointDIntersection(a, b);
        } else {
          // inverser les paramètres
          return calculateur.pointDIntersection(b, a);
        }
     
      }
    }
     
    public class Test {
      public static void main(String[] args) {
        Cercle cercle = new Cercle();
        Ligne ligne = new Ligne();
        cercle.pointDIntersection(cercle);
        ligne.pointDIntersection(ligne);
        cercle.pointDIntersection(ligne);
        ligne.pointDIntersection(cercle);
      }
    }
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  14. #14
    Membre averti
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Entendons-nous bien : c'est abominablement compliqué.
    J’acquiesce !
    Je n'étais pas du tout dans cette logique. Ici c'est la ManagerIntersections classe qui fait le gros du boulot...

  15. #15
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Oui enfin, en situation réelle, le gros du boulot, ce serait tous les calculateurs.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  16. #16
    Membre averti
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Oui enfin, en situation réelle, le gros du boulot, ce serait tous les calculateurs.
    Je ne parlais pas des classes métiers (de calcul) mais de l'aspect gestion des instances de figures géométriques (qui était le sujet initial :"comment limiter les instanceof") qui va rapidement faire grossir ManagerIntersections sans parler de toutes les combinaisons possibles d'intersection (avec plusieurs points...).

  17. #17
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 442
    Par défaut
    Citation Envoyé par hwoarang Voir le message
    Ton architecture a un problème puisque pointDIntersection renvoie des points alors que mathématiquement, ca peut etre infini (par exemple dans le cas d'une droite et d'un segment/une autre droite confondus). Si c'est normal, on peut supposer que tu te places dans un espace discret (c'est à dire non continu) et dans une fenetre finie.
    Dans ce cas, pour avoir une solution générique, on pourrait imaginer créer pour chaque ComposantGraphique une fonction int[] pointsY(int x) qui renvoie les valeurs de y pour chaque point x (en supposant 2 dimensions). Ainsi, il serait plus simple de vérifier les points d'intersection.

    Encore une fois, ca suppose un problème très réducteur par rapport à ce qu'il pourrait etre mathématiquement mais ca peut peut etre te suffire...
    Oui. Il s'agit bien d'un problème réducteur : je veux juste m'intéresser aux points d'intersections afin de les représenter sur mon graphique et de les rendre sélectionnables. Une intersection contenant une infinité de points ne m'intéresse pas et sera juste ignorée.

    Le mieux, selon moi, serait une classe centrale, indépendante, capable de gérer les différents cas,
    Bon, ok. Je crois que je vais partir là-dessus. Merci pour votre aide.

  18. #18
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par WebSteph0 Voir le message
    Je ne parlais pas des classes métiers (de calcul) mais de l'aspect gestion des instances de figures géométriques (qui était le sujet initial :"comment limiter les instanceof")
    Ok. Ben pas le moindre instanceof. Cerise sur le gâteau, les combinaisons sont hachées, pas essayées en chaîne (bon, en réalité avec le HashSet c'est probablement plus cher. Mais ça montre la possibilité d'une implem' de Set dédiée avec un hachage rapide qui en tirerait parti.)

    Citation Envoyé par WebSteph0 Voir le message
    qui va rapidement faire grossir ManagerIntersections sans parler de toutes les combinaisons possibles d'intersection (avec plusieurs points...).
    Ah bah oui mais là il y a pas le choix. Le nombre de combinaisons il est mathématique, on en aura pas moins. Quand c'est possible bien sûr, on préférera se réduire à un dénominateur commun et tout travailler à partir de là. Mais quand ça peut pas ça peut pas.
    Le mieux qu'on puisse faire est de centraliser le démultiplexage deux objets vers le bon algo, pour éviter de le dupliquer dans tous les coins, et aussi éviter de se taper toutes les combinaisons position 1 et position 2 quand l'ordre des objets n'a pas d'importance.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  19. #19
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 442
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    class ManagerIntersections {
      private static final Map<Set<Class<?>>, CalculateurIntersection<?, ?>> map = new HashMap<>();
    
      private static <A extends ComposantGraphique, B extends ComposantGraphique>
        void enregistrerCalculateur(CalculateurIntersection<A, B> calculateur, Class<A> aClass, Class<B> bClass) {
    
        Set<Class<?>> set = new HashSet<>();
        set.add(aClass);
        set.add(bClass);
        map.put(set, calculateur);
      }
    
      static {
        enregistrerCalculateur(new IntersectionCercles(), Cercle.class, Cercle.class);
        enregistrerCalculateur(new IntersectionLignes(), Ligne.class, Ligne.class);
        enregistrerCalculateur(new IntersectionCercleLigne(), Cercle.class, Ligne.class);
      }
    
      public static LinkedList<Point>
        pointDIntersection(ComposantGraphique a, ComposantGraphique b) {
    
        // récupérer le calculateur adéquat
        Set<Class<?>> set = new HashSet<>();
        Class<?> aClass = a.getClass();
        Class<?> bClass = b.getClass();
        set.add(aClass);
        set.add(bClass);
        @SuppressWarnings("unchecked")
        CalculateurIntersection<ComposantGraphique, ComposantGraphique> calculateur =
          (CalculateurIntersection<ComposantGraphique, ComposantGraphique>)map.get(set);
    
        // Gérer le cas où il n'a pas été enregistré
        if(calculateur == null) {
          throw new IllegalArgumentException("Combinaison de composants inconnue");
        }
    
        // Déterminer dans quel ordre appeler les paramètres
        ParameterizedType calculateurType = (ParameterizedType)calculateur.getClass().getGenericInterfaces()[0];
        Type firstType = calculateurType.getActualTypeArguments()[0];
        if(firstType == aClass) {
          // appeler avec le paramètre a en premier
          return calculateur.pointDIntersection(a, b);
        } else {
          // inverser les paramètres
          return calculateur.pointDIntersection(b, a);
        }
    
      }
    }
    
    public class Test {
      public static void main(String[] args) {
        Cercle cercle = new Cercle();
        Ligne ligne = new Ligne();
        cercle.pointDIntersection(cercle);
        ligne.pointDIntersection(ligne);
        cercle.pointDIntersection(ligne);
        ligne.pointDIntersection(cercle);
      }
    }
    J'ai un problème : Les set ne sont pas sensé accepter qu'une seule fois le même objet ? Les lignes que j'ai mises en rouge ne sont-elles pas douteuses ?

    Est-ce qu'il existe en Java une collection non ordonnée, qui permette les doublons ?

  20. #20
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    le set n'acceptent qu'une seul fois chaque item, oui. Mais ce n'est pas un soucis. Quand tu met deux fois Cercle.class, tu as au final un Set avec un seul élément, ce qui ne pose pas de problème outre mesure, il ne fait que servir de clé à la Map.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 10
    Dernier message: 22/03/2006, 10h49
  2. Réponses: 5
    Dernier message: 24/04/2003, 11h47
  3. Surcharger le message d'erreur après un OnException
    Par Tirlibibi dans le forum XMLRAD
    Réponses: 2
    Dernier message: 24/04/2003, 11h42
  4. Réponses: 8
    Dernier message: 20/11/2002, 11h50
  5. comment puis-je recupérer l'extesion du fichier?
    Par mirella dans le forum Langage
    Réponses: 7
    Dernier message: 14/08/2002, 15h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo