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 :

Créer un mapper générique à plus de 2 niveaux


Sujet :

Java

  1. #1
    Membre habitué Avatar de domiq44
    Homme Profil pro
    Inscrit en
    Novembre 2005
    Messages
    301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 301
    Points : 135
    Points
    135
    Par défaut Créer un mapper générique à plus de 2 niveaux
    Bonjour à tous,

    Je voudrais approfondir la discussion suivante que j'ai commencé fin mars :
    http://www.developpez.net/forums/d15...per-generique/.

    Maintenant j'ai une 4ième classe héritant de la classe A.

    Petit rappel:
    • 1 classe racine R
    • 2 classes A et B héritant de R
    • 1 classe Z héritant de A (nouveauté)


    Mais oublions B pour ne s'intéresser que la hiérarchie sur 3 niveaux : Z -> A -> R

    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
    package test.heritage2.model;
     
    public class A extends R {
    	private String ma1;
    	private String ma2;
    	private String ma3;
     
    	@Override
    	public String doSomething(String arg) {
    		return "Class A (" + arg + ")";
    	}
     
    	public A loadFromA(A a) {
    		ma1 = a.ma1;
    		ma2 = a.ma2;
    		ma3 = a.ma3;
    		return this;
    	}
     
    	public String getMa1() {
    		return ma1;
    	}
     
    	public void setMa1(String ma1) {
    		this.ma1 = ma1;
    	}
     
    	public String getMa2() {
    		return ma2;
    	}
     
    	public void setMa2(String ma2) {
    		this.ma2 = ma2;
    	}
     
    	public String getMa3() {
    		return ma3;
    	}
     
    	public void setMa3(String ma3) {
    		this.ma3 = ma3;
    	}
     
    	@Override
    	public String toString() {
    		return "A [ma1=" + ma1 + ", ma2=" + ma2 + ", ma3=" + ma3 + ", " + super.toString() + "]";
    	}
    }
    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
    package test.heritage2.model;
     
    public class R {
    	private String mr1;
    	private String mr2;
    	private String mr3;
     
    	public String doSomething(String arg) {
    		return "Class R (" + arg + ")";
    	}
     
    	public R loadFromR(R r) {
    		mr1 = r.mr1;
    		mr2 = r.mr2;
    		mr3 = r.mr3;
    		return this;
    	}
     
    	public String getMr1() {
    		return mr1;
    	}
     
    	public void setMr1(String mr1) {
    		this.mr1 = mr1;
    	}
     
    	public String getMr2() {
    		return mr2;
    	}
     
    	public void setMr2(String mr2) {
    		this.mr2 = mr2;
    	}
     
    	public String getMr3() {
    		return mr3;
    	}
     
    	public void setMr3(String mr3) {
    		this.mr3 = mr3;
    	}
     
    	@Override
    	public String toString() {
    		return "R [mr1=" + mr1 + ", mr2=" + mr2 + ", mr3=" + mr3 + "]";
    	}
    }
    La petite nouvelle

    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
    package test.heritage2.model;
     
    public class Z extends A {
    	private String mz1;
    	private String mz2;
    	private String mz3;
     
    	@Override
    	public String doSomething(String arg) {
    		return "Class Z (" + arg + ")";
    	}
     
    	public String getMz1() {
    		return mz1;
    	}
     
    	public void setMz1(String mz1) {
    		this.mz1 = mz1;
    	}
     
    	public String getMz2() {
    		return mz2;
    	}
     
    	public void setMz2(String mz2) {
    		this.mz2 = mz2;
    	}
     
    	public String getMz3() {
    		return mz3;
    	}
     
    	public void setMz3(String mz3) {
    		this.mz3 = mz3;
    	}
     
    	@Override
    	public String toString() {
    		return "Z [mz1=" + mz1 + ", mz2=" + mz2 + ", mz3=" + mz3 + ", " + super.toString() + "]";
    	}
    }
    Et le mapping, qui correspond à la solution simple proposée par tchize_ et que j'ai adoptée.

    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
    package test.heritage2;
     
    import test.heritage2.model.A;
    import test.heritage2.model.Z;
    import test.heritage2.model.R;
     
    public class App {
     
    	public static void main(String[] args) {
    		R instR = createR();
    		System.out.println(instR.toString());
     
    		A instA = ceateA(instR);
    		System.out.println(instA.toString());
     
    		Z instZ = ceateZ(instA);
    		System.out.println(instZ.toString());
     
    		String str = instZ.doSomething("pipo des alpes");
    		System.out.println(str);
    	}
     
    	private static R createR() {
    		R instR = new R();
    		instR.setMr1("rrr1");
    		instR.setMr2("rrr2");
    		instR.setMr3("rrr3");
    		return instR;
    	}
     
    	private static A ceateA(R instR) {
    		A instA = new A();
    		instA.setMa1("aaa1");
    		instA.setMa2("aaa2");
    		instA.setMa3("aaa3");
     
    		instA = (A) instA.loadFromR(instR);
    		return instA;
    	}
     
    	private static Z ceateZ(A instA) {
    		Z instZ = new Z();
    		instZ.setMz1("zzz1");
    		instZ.setMz2("zzz2");
    		instZ.setMz3("zzz3");
     
    		instZ = (Z) instZ.loadFromA(instA);
    		return instZ;
    	}
     
    }
    Mais je n'obtiens pas cette fois-ci le résultat que j'attends.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    R [mr1=rrr1, mr2=rrr2, mr3=rrr3]
    A [ma1=aaa1, ma2=aaa2, ma3=aaa3, R [mr1=rrr1, mr2=rrr2, mr3=rrr3]]
    Z [mz1=zzz1, mz2=zzz2, mz3=zzz3, A [ma1=aaa1, ma2=aaa2, ma3=aaa3, R [mr1=null, mr2=null, mr3=null]]]
    Class Z (pipo des alpes)
    Puisque l'instance de la classe Z a bien hérité de l'instance de la classe A, mais pas de l'instance de la classe R.

    Est-ce que cette solution est toujours applicable ?

    Comment solutionner ce problème tout en gardant une solution simple et propre ?

    Merci.

  2. #2
    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
    Personellement, je ferais ça pour commencer:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    	public A loadFromA(A a) {
    		loadFromR(a);
    		ma1 = a.ma1;
    		ma2 = a.ma2;
    		ma3 = a.ma3;
    		return this;  
    	}
    Ensuite, tu peux améloirer:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class R {
       R loadFrom(Object other){
           if (other instanceof R){
              R r = (R) other;
              r1=r.r1;
    //etc
          }
          return this;
       }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class A {
       @override
       A loadFrom(Object other){
           super.loadFrom(other);
           if (other instanceof A){
              A r = (A) other;
              ma1=a.ma1;
    //etc
          }
          return this;
       }
    }
    }

  3. #3
    Membre habitué Avatar de domiq44
    Homme Profil pro
    Inscrit en
    Novembre 2005
    Messages
    301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 301
    Points : 135
    Points
    135
    Par défaut
    Je viens de trouver une solution. Elle se situe au niveau des méthodes loadFromXxx().

    La voici dans R:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class R {
    ...
    	public R loadFromR(R r) {
    		// R
    		setMr1(r.getMr1());
    		setMr2(r.getMr2());
    		setMr3(r.getMr3());
    		//
    		return this;
    	}
    ...
    et aussi dans A:


    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
    public class A extends R {
    ...
    	public A loadFromA(A a) {
    		// A
    		setMa1(a.getMa1());
    		setMa2(a.getMa2());
    		setMa3(a.getMa3());
    		// R
    		setMr1(a.getMr1());
    		setMr2(a.getMr2());
    		setMr3(a.getMr3());
    		//
    		return this;
    	}
    ...
    Ce qui donne le résultat attendu suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    R [mr1=rrr1, mr2=rrr2, mr3=rrr3]
    A [ma1=aaa1, ma2=aaa2, ma3=aaa3, R [mr1=rrr1, mr2=rrr2, mr3=rrr3]]
    Z [mz1=zzz1, mz2=zzz2, mz3=zzz3, A [ma1=aaa1, ma2=aaa2, ma3=aaa3, R [mr1=rrr1, mr2=rrr2, mr3=rrr3]]]
    Class Z (pipo des alpes)
    Mais la solution n'est hélas pas très générique.

    Dans le cas éventuel d'un ajout d'un niveau supplémentaire sur 4 niveaux : Y -> Z -> A -> R, il va falloir modifier beaucoup trop de choses.

    Est-il possible de rendre cela plus générique ?
    Merci.

    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
    package test.mapping.model;
     
    public class Y extends Z {
    	private String my1;
    	private String my2;
    	private String my3;
     
    	public String getMy1() {
    		return my1;
    	}
     
    	public void setMy1(String my1) {
    		this.my1 = my1;
    	}
     
    	public String getMy2() {
    		return my2;
    	}
     
    	public void setMy2(String my2) {
    		this.my2 = my2;
    	}
     
    	public String getMy3() {
    		return my3;
    	}
     
    	public void setMy3(String my3) {
    		this.my3 = my3;
    	}
     
    	@Override
    	public String toString() {
    		return "Y [my1=" + my1 + ", my2=" + my2 + ", my3=" + my3 + ", " + super.toString() + "]";
    	}
    }
    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
    public class Z extends A {
    ...
    	public Z loadFromZ(Z z) {
    		// Z
    		setMz1(z.getMz1());
    		setMz2(z.getMz2());
    		setMz3(z.getMz3());
    		// A
    		setMa1(z.getMa1());
    		setMa2(z.getMa2());
    		setMa3(z.getMa3());
    		// R
    		setMr1(z.getMr1());
    		setMr2(z.getMr2());
    		setMr3(z.getMr3());
    		//
    		return this;
    	}
    ...
    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
    public class App {
     
    	public static void main(String[] args) {
    		...
    		Y instY = createY(instZ);
    		System.out.println(instY.toString());
    	}
    ...
    	private static Y createY(Z instZ) {
    		Y instY = new Y();
    		instY.setMy1("yyy1");
    		instY.setMy2("yyy2");
    		instY.setMy3("yyy3");
     
    		instY = (Y) instY.loadFromZ(instZ);
    		return instY;
    	}
    }

  4. #4
    Membre habitué Avatar de domiq44
    Homme Profil pro
    Inscrit en
    Novembre 2005
    Messages
    301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 301
    Points : 135
    Points
    135
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Personellement, je ferais ça pour commencer...
    Merci encore pour ton aide.

    Ca simplifie beaucoup en effet et cela évite de se poser trop de question.

    Est-t-il possible (je pense à la généricité) d'éviter ces instanceOf ?

    Une des classes modifiée:

    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
    package test.mapping.model;
     
    public class A extends R {
    	private String ma1;
    	private String ma2;
    	private String ma3;
     
    	@Override
    	public A loadFrom(Object other) {
    		super.loadFrom(other);
    		if (other instanceof A) {
    			A instA = (A) other;
    			setMa1(instA.getMa1());
    			setMa2(instA.getMa2());
    			setMa3(instA.getMa3());
    		}
    		return this;
    	}
     
    	public String getMa1() {
    		return ma1;
    	}
     
    	public void setMa1(String ma1) {
    		this.ma1 = ma1;
    	}
     
    	public String getMa2() {
    		return ma2;
    	}
     
    	public void setMa2(String ma2) {
    		this.ma2 = ma2;
    	}
     
    	public String getMa3() {
    		return ma3;
    	}
     
    	public void setMa3(String ma3) {
    		this.ma3 = ma3;
    	}
     
    	@Override
    	public String toString() {
    		return "A [ma1=" + ma1 + ", ma2=" + ma2 + ", ma3=" + ma3 + ", " + super.toString() + "]";
    	}
    }

  5. #5
    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
    Citation Envoyé par domiq44 Voir le message
    Est-t-il possible (je pense à la généricité) d'éviter ces instanceOf ?

    Une des classes modifiée:
    C'est compliqué. De plus si c'était possible, le compilateur ne pourrait plus garantir qu'il n'y aurait pas d'erreur.

    Exemple, imaginons que THIS soit le type générique qu'on soit arrivé à définir tel que dans la classe A il représente A, dans la classe B il représente B


    classe A,: public THiS loadFrom(THIS autre) -> autre est de type A j'ai accès aux propriétés de a
    classe B extends A: public THiS loadFrom(THIS autre) -> autre est de type B j'ai accès aux propriétés de b

    coté A et B aucun soucis, je peux créer mon code.


    coté utilisation par contre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    A a = new A();
    A a2 = new B();
    a2.xyz(a);
    execute xyz sur une instance de B qui s'attends à recevoir une autre instance de B en paramètre et ça foire.
    Pourtant le compilateur a bien vérifié: a2.xyz, comme a2 est déclaré A, a2 prend en paramètre un A.....


    Donc t'es coincé, si tu veux t'en sortir sans instanceOf, il faut oublier l'héritage de loadFrom et revenir à ton idée de départ du loadFromA, loardFromB, loadFromC,.....

    C'est d'ailleurs pour ça que la méthode clone() est déclarée retournant un Object et non pas un générique: pas possible de définir ce générique.

  6. #6
    Membre habitué Avatar de domiq44
    Homme Profil pro
    Inscrit en
    Novembre 2005
    Messages
    301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 301
    Points : 135
    Points
    135
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    C'est compliqué. De plus si c'était possible, le compilateur ne pourrait plus garantir qu'il n'y aurait pas d'erreur.
    Oui, effectivement. Je comprends.

    De toute façon, le résultat est plus que satisfaisant.
    Merci pour tout tchize_.

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

Discussions similaires

  1. Créer un mapper générique
    Par domiq44 dans le forum Général Java
    Réponses: 4
    Dernier message: 31/03/2015, 08h12
  2. [XPATH]Créer une expression générique
    Par virgul dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 30/04/2008, 09h23
  3. [Word 2007]Table des matières de plus de 3 niveaux
    Par jo_dalton dans le forum Word
    Réponses: 1
    Dernier message: 12/03/2008, 06h38
  4. Réponses: 1
    Dernier message: 12/11/2007, 16h49
  5. [Conception] créer une page : les plus consultées
    Par akara dans le forum Langage
    Réponses: 3
    Dernier message: 29/08/2007, 11h57

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