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 :

Problème de référence/cast (héritage)


Sujet :

Java

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    759
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 759
    Par défaut Problème de référence/cast (héritage)
    Bonjour,

    Note : la notion mère/fille était inversée dans ma description comme le fait remarquer justement Deaf


    1) J'ai une classe mère ClasseM qui a un certain nombres d'arguments et une classe fille ClasseF qui ajoute certains champs en plus des champs de ClasseM dont elle dérive.

    2) J'ai une fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ClasseF ajouterInformation (ClasseF arg){
    
    ClasseM m = (ClasseM)arg; //ici on croit qu'on cast mais pas du tout quand on regarde l'objet f qui reste de type ClasseF !
    m = ajouterInformation(m); //ajouterInformation ne traite que des objets ClasseM
    arg = (ClasseF)m; //c'est mal dans ce sens en théorie
    //...
    //Et ici on traite la partie spécifique aux champs de ClasseF
    
    return arg;
    }
    Ci-dessus, on a des cast qui ne devraient pas être faits comme ça...mais ça marche ClasseM --> ClasseF devrait générer une erreur mais comme le premier cast n'a fait que semblant de marcher, ça passe!

    --------------------------

    Pour faire plus propre, j'ai créé dans ma classe mère une fonction castToClasseM et un constructeur new ClasseF (ClasseM f)

    Mais si je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ClasseF ajouterInformation (ClasseF arg){
    
    ClasseM m = arg.castToClasseM(); //OK
    m = ajouterInformation(m); //OK
    ClasseF ret = new ClasseF (m); //on perd les références issus de arg à la sortie de la fonction puisque l'objet arg est détruit par le garbage collector
    //...
    //Et ici on traite la partie spécifique aux champs de ClasseF 
    
    return ret;
    }
    L'objet retourné perd un certain nombre des propriétés qu'avait arg en entrée.

    Comment faire du mieux possible?
    Merci.

  2. #2
    Membre émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    Bonjour,

    J'ai l'impression que tu as mélangé les termes : en fait ta classe "fille" ClasseF est la mère de ta classe "mère" ClasseM (qui est donc la fille...).

    Si on passe ce détail, ceci est inutile:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClasseF f = (ClasseF)arg;
    En effet, f est une instance de ClasseM qui hérite de ClasseF, donc f est de type ClasseF par définition.

    Après, pour la suite, on manque d'infos sur ce que font la méthode castToClasseF et le constructeur.

    Cependant, l'héritage ne doit pas engendrer des manipulations de type de ce genre là. Je pense que tu pars dans la mauvaise direction.

    Que cherches-tu à faire exactement?

  3. #3
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2007
    Messages
    697
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2007
    Messages : 697
    Par défaut
    J'ai l'impression que tu comprends mal comment marche le cast sur les objet en Java. Comme tu as pu t'en rendre compte, l'objet n'est jamais casté. C'est la référence qui est castée. Il n'y a donc pas de perte d'informations au niveau de l'objet mais seulement au niveau de la référence. Je ne sais pas si tu a fait du C/C++ mais on peut comparer ça au cast sur les pointeurs d'objets et non au cast sur les objets eux mêmes.

    Ensuite par rapport au cast, le cast de la classe fille vers la classe mère est implicite et ne nécessite pas d'utiliser l'opérateur (typeDestination). Ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    TypeMere m = new TypeFille();
    est parfaitement légal et est même souvent une bonne pratique.

    Par contre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    TypeFille f =  (TypeFille)m;
    impose généralement de tester avant de la façon suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if(m instanceof TypeFille){
      TypeFille f =  (TypeFille)m; 
    }
    Cette opération (downcasting) n'est pas recommandée et souvent causée par une mauvaise conception.

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    759
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 759
    Par défaut
    Merci pour vos réponses.

    Pour la suite, j'ai modifié dans ma description les termes de classe mère et fille qui effectivement étaient inversés. Ca permettra de mieux comprendre.

    Alors ce que je veux faire :
    j'ai une grosse fonction ClasseM ajouterInformation(ClasseM in) qui fait un certain nombre de traitements de complétions sur l'objet de type ClasseM.

    La fonction ClasseF ajouterInformation(ClasseF in) quant à elle fait la même chose sur la partie commune (la partie ClasseM) et ajoute un certain nombre de traitements de complétions sur les champs spécifiques à la classe ClasseF.

    Est-ce que c'est plus clair?

  5. #5
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    J'ai du mal à comprendre le soucis. Ceci devrait marcher :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class ClasseM {
    	ClasseM ajouterInformation(ClasseM in) {
    		// code pour ClasseM
    		return in;
    	}
    }
     
    class ClasseF extends ClasseM {
    	ClasseF ajouterInformation(ClasseF in) {
    		ajouterInformation((ClasseM)in);
    		// code pour ClasseF
    		return in;
    	}
    }
    Pourrais-tu détailler ce qui te pose problème, avec un code a-minima qui le reproduise ?


    Et quel est l'objectif final de tout cela ???


    a++

  6. #6
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    En Java le cast ne change pas le type réel de l'objet. Juste la manière dont il est déclaré...


    a++

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    759
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 759
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Salut,
    J'ai du mal à comprendre le soucis. Ceci devrait marcher (...)
    D'une part ces fonctions ajouterInformation ne sont pas dans mes classes ClasseM et ClasseF mais dans mes services.
    D'autre part c'est plus ou moins ce que je décris :
    un cast ClasseF vers ClasseM qui fait semblant de caster (car quand on observe l'objet, ça reste du ClasseF) et ensuite un cast ClasseM vers ClasseF de l'objet enrichi dans la première étape.

    Mais si ça se trouve, en faisant ça, ça semble mal mais on peut manipuler l'objet ClasseF et le traitant comme un ClasseM quand on en a besoin, et de continuer à le traiter comme un ClasseF pour la suite (alors que dans ce que j'écrivais, j'avais l'impression de réellement changer de classe).

  8. #8
    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 stof Voir le message
    Mais si ça se trouve, en faisant ça, ça semble mal mais on peut manipuler l'objet ClasseF et le traitant comme un ClasseM quand on en a besoin, et de continuer à le traiter comme un ClasseF pour la suite (alors que dans ce que j'écrivais, j'avais l'impression de réellement changer de classe).
    Ben oui... C'est à ça que ça sert, les hiérarchies de classes -_-°.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    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
    C'est le principe de base de l'héritage: une classe enfant peux toujours se substituer à une classe parent dans une opération. Une voiture est un objet, une smart est une voiture (enfin pas vraiment mais c'est une autre histoire).

    Si j'ai un Garage dans lequel je peux mettre des voiture, je peux y mettre une smart, mais pas un semi-remorque. Si j'ai des possessions dans lesquelles je peux mettre des objet, je peux y mettre des semi-remorques et des smart


    La seul chose très particulière dans ton cas, c'est la présence de deux méthodes dans classeF qui ont le même nom:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ajouterInformation(ClasseM in)
    ajouterInformation(ClasseF)
    hors quand on fait dans ce cas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ajouterInformation(fille);
    le compilateur trouve les deux méthodes compatibles (puisque la fille est aussi une mère). Il choisi alors la méthode qui est la plus explicite (fille). Quand tu veux explicitement appeler ajouterInformation(ClasseM in), il faut en informer le compilateur en faisant un cast explicite. C'est un des rare cas où il est nécessaire de faire un cast explicite vers le parent.

    En fait, on peux résumer ton problème sans avoir besoin de créer deux classes. Imaginons cette classe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public void add(JPanel panneau) {......}
    public void add(Object o){.....}
    public void add(JButton button) {.....}
     
    public void monCode(){
        JPanel panel1 = new JPanel();
        JPanel panel2 = new JPanel();
        JButton button = new JButton("Coucou");
        add(panel1); // appel première méthode 
        add(button); // appel troisième méthode
        add((Object)panel1); // appel explicite vers la deuxième méthode
    }

    A notre que dans ton cas, il existe une alternative au cast pour informer le compilateur:


    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
    public class Mere {
        //...
        public void ajouterInformation(Mere autre){....}
    }
    public class Fille extends Mere {
        public void ajouterInformation(Fille autre){
            super.ajouterInformation(autre); // appel explicite de l'autre méthode dans le parent
        //....
     
        }
    }
     
    public static void main {
         Fille f  = new Fille();
         f.ajouterInformation(new Fille());
    }

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    759
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 759
    Par défaut
    Je vois à peu près maintenant.

    Donc on peut faire (ces fonctions ne sont pas dans mes classes pour rappel) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    1°] ClasseFille f = new ClasseFille ();
    2°] ClasseMere m = (ClasseMere) f;
    3°] m = ajouterInformation(m); //on touche à la partie ClasseMere de f
    4°] f.setChampSpe("toto"); //on retrouve notre objet de départ f donc la partie héritée de ClasseMere a été enrichie dans 3°]

  11. #11
    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
    oui, d'ailleurs, tu remarquera que m==f renvoie true

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de référence de classe
    Par nmathon dans le forum Delphi
    Réponses: 7
    Dernier message: 21/06/2006, 16h46
  2. [FLASH MX2004] this et problème de référence
    Par cristolb dans le forum ActionScript 1 & ActionScript 2
    Réponses: 5
    Dernier message: 03/05/2006, 22h33
  3. Problème de référence de données circulaire
    Par Wismerhill50 dans le forum Langage
    Réponses: 3
    Dernier message: 23/10/2005, 22h38
  4. problème de références _ptr dans une map STL
    Par Mr_Tyu dans le forum CORBA
    Réponses: 1
    Dernier message: 10/08/2004, 10h39
  5. Réponses: 2
    Dernier message: 25/07/2004, 23h24

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