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

Langage Java Discussion :

Problème d'héritage de plusieures classes


Sujet :

Langage Java

  1. #1
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 5
    Par défaut Problème d'héritage de plusieures classes
    Bonjour à tous !

    Je rencontre un problème lié à l'héritage dans un jeu que je programme. Je m'explique, j'ai deux classes : Table et Joueur. La classe Table utilise la classe Joueur, et la classe Joueur utilise la classe table.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class Table {
    private Joueur joueur;
    public Joueur getJoueur() {return joueur;}
    ...
    }
     
    class Joueur {
    private Table table;
    public Table getTable() {return table;}
    ...
    }
    J'aimerais maintenant construire 2 classes, STable et SJoueur, qui héritent respectivement de Table et Joueur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class STable extends Table {
    public SJoueur getSJoueur() {return joueur;}
    ...
    }
     
    class SJoueur extends Joueur {
    public STable getSTable() {return table;}
    ...
    }
    Le problème vient du fait que dans les classes mères, les objets sont de type Table et Joueur. Dans ces classes mères, j'ai des méthodes qui utilisent les variables de classes dans des méthodes. Comment faire pour pouvoir hériter de ces méthodes dans les classes filles et faire en sorte qu'elles utilisent des variables de type STable/SJoueur ? Il est impossible de changer le type des variables, mais n'est-il pas possible de transformer un Joueur en SJoueur pour pouvoir utiliser la même méthode dans Table et STable ?

    Solutions envisagées :
    J'ai d'abord envisagé de garder les variable de STable en tant que Joueur (et vise-versa), et de les caster quand ce sera nécessaire. Est-ce que cela sera toujours possible ?

    J'ai aussi envisagé d'utiliser des generics, mais alors je me retrouve avec ce genre de problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    class Table<J extends Joueur<T extends Table<J extends Joueur<T extends Table<...>>>>> {
    ...
    }
    Bref, le fait que chaque classe est paramétrée par un type qui étends l'autre, ça fait une boucle infinie... J'ai alors pensé déclarer ma classe comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    class Table<J extends Joueur<?>> {
    ...
    }
    Mais cela crée d'autre problème pour des méthode qui utilisent les types generics (je peux détailler si besoin...).

    Bref, comment puis-je faire 2 classes filles qui héritent de deux classes qui s'utilisent mutuellement ?

    Merci à tous de votre aide !

  2. #2
    Membre chevronné
    Profil pro
    Développeur Java
    Inscrit en
    Novembre 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2007
    Messages : 301
    Par défaut
    Oula, cela sent la mauvaise conception à plein nez.

    Pour répondre à ta question initiale, on ne peut pas faire d'héritage multiple et ce n'est pas nécessaire. Le fait de pouvoir implémenter des interfaces suffit amplement à gérer tous les cas existants.

    Pour en venir à ma première remarque, ta conception semble tordue. Déjà pourquoi un joueur combien une table et une table contient un joueur ? Je ne sais pas trop ce que tu modélises par une table donc je ne peux pas t'aider mais il y a clairement un problème ici.

    De plus, l'héritage n'est pas fait pour faire n'importe quoi et récupérer des méthodes à des classes mères. On utilise l'héritage lorsque la classe fille est une spécialisation de la classe mère. Si on ne peut pas dire que la classe fille est une classe mère alors il faut mieux utiliser la composition.

    Je ne sais pas là non plus ce que tu veux faire mais peut être que la solution est simplement d'avoir une classe avec une table et un joueur. Ça ne semble quand même pas terrible pour l'instant si dans l'une ou l'autre il y a soit un joueur soit une table.

    Je pense qu'en reprenant ta conception et en réalisant un diagramme de classe où l'on voit bien apparaître les dépendances entre les classes alors cela pourrait t'aider à résoudre ton problème.

  3. #3
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 5
    Par défaut
    J'aurais du préciser un peu plus la conception générale. J'ai appris java sur le tas, et je suis avide de conseils sur la conception de programme ou leur architecture...

    Revenons à nos moutons :

    - En fait, une table contient plusieurs joueurs. Je n'en ai mentionné qu'un ici pour simplifier le problème.

    - Il s'agit d'une application client/serveur. Les classes Table et Joueur modélisent des actions générales relative à la table ou au joueur (ajout d'un joueur à une table, état de jeu dans lequel se trouve la table, etc.). Les classes STable et SJoueur sont utilisées uniquement par le serveur, et elles rajoutent, par rapport à leurs classes mères, certaines fonctionnalités qui ne sont utilisées que par le serveur (calcul des points, calcul des positions des joueurs, etc.). L'héritage me semblait ici une bonne idée puisque les classes filles "étendent" réellement le concept des classes mères, tout en leur donnant de nouvelles fonctionnalités. J'aurai également besoin de créer les classes CTable et CJoueur, pour la version client. Certaines fonctionnalités sont aussi différente d'un cas à l'autre. Quand un joueur joue, il se passe une action différente sur la table du serveur et sur celle du client.

    - La table est liés à tous les joueurs présent à la table, et chaque joueur est lié à la table où il est présent par facilité. Lorsqu'un joueur envoie un message au serveur, le serveur sait à quelle table il est, et retrouver tous les joueurs qui sont à cette table, etc.

    En tout cas, merci déjà pour ta première réponse

  4. #4
    Membre chevronné
    Profil pro
    Développeur Java
    Inscrit en
    Novembre 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2007
    Messages : 301
    Par défaut
    Je pense qu'effectivement que tu as un problème de conception. Après une petite reflexion, voici comment je vois les choses.

    Il faut voir premièrement que le client et le serveur ne s'échangent que des données, ils n'ont pas à savoir vraiment comment de chaque côté les données vont être traités. Dès lors, il n'y a plus de raison d'avoir de l'héritage ou quoi que se soit.

    On pourrait effectivement créer deux classes VO (Value Object contenant uniquement des données) qui seraient Joueur et Table. Le client et le serveur partagerait aussi une interface Service qui permet au client d'appeler des méthodes du serveur qui lui les implémente (via RMI par exemple).

    Les services seraient par exemple, de créer une table avec la table en paramètre (le VO), d'ajouter un joueur à la table et tous les éléments du jeu à proprement parler (miser, finir la partie, etc.).

    Côté serveur, il y aurait donc l'implémentation de l'interface que l'on mettrait dans un package controller. Ensuite, il pourrait y avoir un deuxième package application ou métier où ils pourraient y avoir soit des classes de services qui traitent ces informations et les envoies aux autres joueurs soit des objets métiers. Les objets métiers, eux peuvent prendre les VO en paramètre et recopier toutes les valeurs à l'intérieur et proposer de nouvelles méthodes. Enfin, il pourrait y avoir un package dao pour sauvegarder les données dans une base. (L'architecture présentée ici est l'architecture J2EE 3-tier classique).

    Côté client, il peut donc y avoir une partie qui s'occupe de l'affichage et une autre qui s'occupe du traitement du jeu. Elle peut faire appels aux services et créer les VO qui seront traités par le serveur.

    Voilà comment je vois les choses. Après, fouille un peu sur internet, il doit probablement y avoir des sources sur des jeux en client/serveur via socket ou RMI.

  5. #5
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 5
    Par défaut
    Ce que tu dis semble intéressant. Je ne comprends pas tout, je vais donc "googeller" pour en apprendre plus...

    A ce que j'ai compris, tu conseilles que l'implémentation soit faite uniquement du côté du serveur ?

    En fait, dans mon appli, les classes Table et Joueur font partie du Modèle. J'utilise le Modèle du coté serveur évidement, pour modéliser les données, mais également du côté client, que j'ai implémenté avec l'architecture de modèle-vue-controlleur. Quand cette architecture est utilisée dans une appli réseau, le modèle doit-il uniquement être présent du côté serveur ? A première vue cela me semble étrange du point de vue des requêtes qu'il faudra multiplier à cause de tout ce qu'il faudra envoyer au client...

    J'insiste un peu sur mon idée de modèle partagé, mais n'hésite pas à me contredire
    Mais je pense que des actions sont communes, comme je l'ai dit : ajouter des joueurs à une table, mettre les joueurs dans une équipe dans la table, compter les mises de chaque joueur, compter les actions de chaque joueur, tout cela semble être des actions que le serveur et le client doivent connaître.
    Par contre le fait de compter les points ne peut se faire que du côté serveur, qui le transmet ensuite au client.
    Du coté client, il y a la partie où il prévient les listeners (du modèle-vue-controlleur) à chaque fois que le modèle change, ce que le serveur n'a pas besoin de savoir.

    Enfin, je vais me renseigner sur la manière que tu me conseilles et je reviens te dire quoi Merci pour l'aide

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 155
    Par défaut
    J'ai essayé de faire ton truc, et bien ca marche, je voit pas ton probleme.

    donc avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    class A <BB extends B>{
     BB monb;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    class CA extends A<CB>{
     String ca="ca";
     doCa(){ System.err.println("cb="+monb.cb);
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    class SA extends A<SB>{
     String sa="sa";
     doSa(){ System.err.println("sb="+monb.sb);
    }
    et pareil pour le B, CB, SB
    ba ca compile et ca marche bien.

  7. #7
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 5
    Par défaut
    Salut merill,

    Je supposes que tu fais la classe B comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    class B <AA extends A>{
     AA mona;
    }
    Il faut alors modifier la classe A :

    Citation Envoyé par merill Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class A <BB extends B<?>>{
     BB monb;
    }
    ... puisque B est un type paramétré. (Et idem pour B)

    Maintenant si j'utilise, dans la classe B, une variable de type AA comme paramètre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class B <AA extends A<?>>{
     AA mona;
     
     public void maMethode(AA una) {...}
    }
    Le code suivant ne compile plus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class A <BB extends B<?>>{
     BB monb;
    
     public void methode() {
      monb.maMethode(this);
     }
    }
    L'erreur renvoyée est la suivante :
    Exception in thread "Thread-3" java.lang.Error: Unresolved compilation problem:
    Bound mismatch: The method maMethode(?) of type BB is not applicable for the arguments (A<BB>). The wildcard parameter ? has no lower bound, and may actually be more restrictive than argument A<BB>
    As-tu un moyen de passer outre ce problème ?

    Merci pour tes conseils !

  8. #8
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 155
    Par défaut
    Je fais la classe B comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    class B <AA extends A>{
     AA mona;
    }
    Mais je n'ai pas besoin de modifier la classe A.
    (j'utilise le jdk 6)
    en fait, c'est à peu près comme si je fesais A <BB extends B<?>> mais pas besion de marquer le <?>, ca compile tout seul.

    Tu utilise quoi pour ca te geule dessus?
    ps: je te mp le code complet de mon exemple.

Discussions similaires

  1. Problème d'héritage et de classe abstraite
    Par Guillaume1701 dans le forum Débuter avec Java
    Réponses: 3
    Dernier message: 01/04/2015, 23h18
  2. [Conception] Héritage sur Plusieurs classes abstraites
    Par facilus68 dans le forum Langage
    Réponses: 9
    Dernier message: 20/03/2009, 13h06
  3. Problème d'héritage avec une classe abstraite
    Par Ph.denis dans le forum C++
    Réponses: 7
    Dernier message: 22/03/2008, 10h37
  4. Réponses: 2
    Dernier message: 26/10/2006, 10h13
  5. Réponses: 3
    Dernier message: 15/05/2006, 19h04

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