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 :

héritage inverse générique


Sujet :

Langage Java

  1. #1
    Candidat au Club
    Inscrit en
    Février 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 5
    Points : 2
    Points
    2
    Par défaut héritage inverse générique
    Bonjour,
    je cherche un mécanisme générique qui permet de passer d'une instance d'une classe mère à une instance d'une classe fille héritée.
    exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public class Mere {
        public Mere() {}
     
        public Mere(String name) {
            this.name = name;
        }
     
        public String getName() {
            return name;
        }
     
        String name;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public class Fille extends Mere {
        public Fille() {
            super();
        }
        public static void main(String[] args) {
            Mere mere = new Mere();
            Fille fille = (Fille) mere; // Cast impossible
        }
    }
    Je cherche donc un mécanisme qui permet de convertir un type parent en type hérité de manière générique, sans utiliser de constructeur par recopie.

    Je recherche quelque chose du style.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Object Converter.convert(Object parent, Object hérité)
    où parent est une instance déjà existante et hérité le type que je souhaite obtenir en retour. Je pense que cela doit être faisable avec la réflexion, et peut-être existe-t-il des API faisant cela.

    Merci d'avance.

  2. #2
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par memedidou Voir le message
    sans utiliser de constructeur par recopie.
    C'est la seule solution !

    a++

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    houlà, tu cherche à faire des trucs bizzares

    Tu peux éventuellement, si Mere et Fille ont tous les deux un constructeur générique, passer par PropertyUtils.copyProperties() de commons beanutils (projet jakarta)

  4. #4
    Membre habitué
    Inscrit en
    Décembre 2004
    Messages
    201
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Décembre 2004
    Messages : 201
    Points : 179
    Points
    179
    Par défaut
    En effet, je pense que tu dois pouvoir obtenir quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Mere mere = new Mere();
    Fille fille = (Fille)Converter.convert(mere, Fille.class);

  5. #5
    Candidat au Club
    Inscrit en
    Février 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    C'est presque ce qu'il me faut, ca avance vite !

    J'ai essayé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PropertyUtils.copyProperties(fille, mere);
    Par contre, ca ne marche que dans le cas ou la classe mère possède un ensemble de setter.
    Or ma classe Mere ne possède pas que des couples get/set mais aussi des "put" dans des HashMap et des get de ces HashMap.
    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
    import java.util.HashMap;
     
    public class Mere {
     
        public Mere() {
            map = new HashMap<String, String>();
        }
     
        public void setName(String name) {
            this.name = name;
        }
     
        public String getName() {
            return name;
        }
     
        public void addElement(String key, String value) {
            map.put(key, value);
        }
     
        public HashMap<String, String> getMap() {
            return map;
        }
     
        private String name;
        private HashMap<String, String> map;
     
    }
    je continue de chercher dans ce que fournit Apache.
    Si il y a d'autres idées ?

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    ben si tu veux que ce soit transférable, va falloir mettre ta hasham avec un setter

  7. #7
    Candidat au Club
    Inscrit en
    Février 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    merci de ce conseil très constructif
    mais si je poste ce problème, c'est bien parce que je ne peux pas modifier le code de la classe Mere.

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    be va falloir que ton Converter traite le cas particulier de la hashmap pour la trasférer

  9. #9
    Membre habitué
    Inscrit en
    Décembre 2004
    Messages
    201
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Décembre 2004
    Messages : 201
    Points : 179
    Points
    179
    Par défaut
    Citation Envoyé par theyankee76 Voir le message
    En effet, je pense que tu dois pouvoir obtenir quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Mere mere = new Mere();
    Fille fille = (Fille)Converter.convert(mere, Fille.class);
    Utilise quelque chose qui ressemble à cela Très utile la réflection

    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
     
    for (Field fieldSource : objectSource.getClass().getDeclaredFields()) {
                fieldSource.setAccessible(true);
                Field fieldDest;
     
                try {
                    fieldDest = objectDest.getClass().getSuperclass().getDeclaredField(fieldSource.getName());
                    fieldDest.setAccessible(true);
                    fieldDest.set(objectDest, fieldSource.get(objectSource));
                    fieldDest.setAccessible(false);
                } catch (SecurityException e) {
                    e.printStackTrace();
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } finally {
                    fieldSource.setAccessible(false);
                }
            }

  10. #10
    Candidat au Club
    Inscrit en
    Février 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    Ok, j'ai fait comme ca et ca marche impec !

    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
    import java.lang.reflect.Field;
     
    public class Converter {
        /**
         * Convert an object to another respecting the choosen class Destination.
         * It makes downcasting from parent to child.
         * 
         * @param classDest the class to which you want a new object
         * @param objectSource the object to convert
         * @return an instance of classDest initialized with objectSource values
         */
        public static Object convert(Class<?> classDest, Object objectSource) {
            if (!objectSource.getClass().equals(classDest.getSuperclass())) {
                System.out.println("Incompatible Class");
                return null;
            }
     
            Object objectDest = null;
            try {
                objectDest = classDest.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
     
            for (Field fieldSource : objectSource.getClass().getDeclaredFields()) {
                fieldSource.setAccessible(true);
                Field fieldDest;
     
                try {
                    fieldDest = objectDest.getClass().getSuperclass().getDeclaredField(fieldSource.getName());
                    fieldDest.setAccessible(true);
                    fieldDest.set(objectDest, fieldSource.get(objectSource));
                    fieldDest.setAccessible(false);
                } catch (SecurityException e) {
                    e.printStackTrace();
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } finally {
                    fieldSource.setAccessible(false);
                }
            }
            return objectDest;
        }
    }
    L'avantage de ce converter est qu'il ne fait pas de recopie car les attributs de l'objet dest et source ont les mêmes "id".
    On peut enfin faire du transtypage descendant (downcasting) !!!

    Par contre, un utilisateur peu scrupuleux peut quand à lui obtenir la valeur d'une variable qui est considérée comme "private" de manière très simple.

    Merci à tous.

  11. #11
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par memedidou Voir le message
    On peut enfin faire du transtypage descendant (downcasting) !!!
    Ce n'est pas du downcasting, puisque qu'un cast ne change en rien le type réel de l'objet.

    Le downcasting correspond tout simplement à ce qu'on appelle généralement un cast :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Mere mere = new Fille();
    Fille fille = (Fille) mere;


    Citation Envoyé par memedidou Voir le message
    Par contre, un utilisateur peu scrupuleux peut quand à lui obtenir la valeur d'une variable qui est considérée comme "private" de manière très simple.
    Et en environnement protégé ton code ne pourra fonctionner que si tu as les droits "suppressAccessChecks". Un constructeur par recopie aurait été plus simple à mettre en place...



    Par curiosité : quel est la finalité de tout cela ?


    a++

  12. #12
    Candidat au Club
    Inscrit en
    Février 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    J'utilise un grand nombre de classes Mere que j'ai besoin d'étendre avec en plus une ou plusieurs nouvelles implémentations.
    Or je ne récupère que des instances de classes Mere et j'ai besoin d'utiliser des instances de classes Fille, d'où mon besoin de "caster" ma classe Mere en Fille.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public class Fille extends Mere implements AutreInterface {
        public Fille() {
            super();
        }
        public AutreMethodImplemented() {
            //code de l'implémentation à utiliser
        }
    }
    Cette façon de faire m'a parue la plus simple à mettre en place. Ca me semble aussi plus propre qu'un constructeur par recopie car si un nouvel attribut et ajouté à la classe Mere, celui ci n'est pas automatiquement recopié (par le constructeur) dans la classe Fille.

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    un "bon" design dans ce genre de cas serait plutot, je pense:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public class Machin implements AutreInterface{
        protected Mere mere;
        public Machin(Mere mere){
            this.mere=mere;
        }
        public Mere getMere(){
            return mere;
        }
        public void autreChose(){
          //TODO
        }
     
    }
    Ca c'est pour le plus propre, mais çà conviens pas nécessairement à tout. Une autre solution c'est le delegate Pattern, un peu plus dur à gérer, mais toujours potable:
    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
     
    public Fille extends Mere implement AutreInterface{
     
        private Mere delegate;
        public Fille(Mere mere){
            this.delegate=mere;
        }
        // implement AutreInterface 
        public void autreChose(){
          //TODO
        }
        // delegate call to truc
        public void truc(){
            delegate.truc();
        }
        // delegate call to setThing
        public void setThing(Thing thing){
            delegate.setThing(thing);
        }
    }
    L'avantage, c'est que pour les appel délégué, tu pose ton curseur sur la déclaration de "Mere delegate" dans eclipse puis tu va dans source -> generate delegate methods, çà va scanner la classe et faire tous les appels délégué.

    Avantage:
    Si Mere à un lifecycle particulier, géré par un truc extérieur, tu ne l'altère pas (t'ajoute juste une coque sur un objet existant, sans détruire cette objet)
    Si Mere est utilisé ailleurs, les Changement sur Fille sont refleté sur l'objet de type Mere, et vice-versa.

    J'ai utilisé cette technique quand j'ai du décorer des objets session hibernate, j'avais pas facilement le controle sur leur production -> utilisation d'un Delegate pattern.

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

Discussions similaires

  1. Relation inverse vers une collection avec héritage
    Par Julienoune dans le forum Hibernate
    Réponses: 0
    Dernier message: 18/03/2009, 06h09
  2. héritage et pointeur générique de type classe mere
    Par contremaitre dans le forum C++
    Réponses: 12
    Dernier message: 07/01/2009, 13h51
  3. Classe générique et héritage
    Par Picolo18 dans le forum Langage
    Réponses: 17
    Dernier message: 14/12/2008, 14h17
  4. type générique avec héritage multiple
    Par apqmwnqmap dans le forum Langage
    Réponses: 4
    Dernier message: 13/03/2008, 14h56
  5. Héritage de package génériques
    Par AlienAttack2k dans le forum Ada
    Réponses: 1
    Dernier message: 23/07/2007, 09h44

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