Précédent   Forum du club des développeurs et IT Pro > Java > Général Java > Langage
Langage Forum d'entraide sur le langage Java et autres langages pour la JVM : syntaxe, POO, conventions, API standard. Avant de poster -> FAQ Java
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 05/01/2013, 14h27   #1
<_oodTi96Tiboo_>
Candidat au titre de Membre du Club
 
Inscription : décembre 2006
Messages : 61
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : décembre 2006
Messages : 61
Points : 11
Points : 11
Par défaut Utilisation des generics

Bonjour a tous,

je cherche à créer une structuration de class manipulant des objets qui peuvent être des doubles ou des complexes.

Afin de ne pas écrire plusieurs fois les class Point2D, Point3D, vector, matrix... qui manipule soit des doubles soit des complexes j’aimerai utiliser les generics.

J'ai donc créé des class (Point2D, Point3D, vector, matrix...) manipulant des :
MyNumber<>

MyDouble et MyComplex sont des MyNumber<>

Or j'ai un problème à la compilation comme définie en suivant:

Code :
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
public interface Numeric<Type> extends Comparable<Type>{
	public abstract Type atan2(Type v);
	public abstract Type atan2(double d);
	public abstract Type sin();
	public abstract Type sinh();
	public abstract Type cos();
	public abstract Type cosh();
	public abstract Type tan();
	public abstract Type add(Type v);
	public abstract Type add(double d);
	public abstract Type sub(Type v);
	public abstract Type sub(double d);
	public abstract Type cube();
	public abstract Type sqrt();
...
}

public abstract class MyNumber<T> extends Number implements Numeric<T>{...}
public class MyDouble extends MyNumber<MyDouble> {...}
public class MyComplex extends MyNumber<MyComplex> {...}


public class Triedre<Type extends MyNumber<Type>>{
...
	private Type a;
	private Type b;
	private Type c;
	
	public Triedre(Type a, Type b, Type c) {
		this.a = a;
		this.b = b;
		this.c = c;
	}

	public Triedre(double a, double b, double c) {
		this.a = new MyDouble(a); // erreur de compilation
		this.b = new MyDouble(b); // erreur de compilation
		this.c = new MyDouble(c); // erreur de compilation
	}
...
}
en résumé :
- MyDouble est de type "MyNumber<MyDouble>"
- le type "Type" dans la class Triedre est de type "MyNumber<Type>"

comment faire en sorte que les types soit compatible?

Merci d'avance pour votre support.
Sébastien.
<_oodTi96Tiboo_> est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2013, 16h39   #2
thelvin
Modérateur
 
Inscription : septembre 2004
Messages : 7 097
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 7 097
Points : 10 327
Points : 10 327
Envoyer un message via Skype™ à thelvin
Une double est un double, il n'a pas besoin de paramètre et ne peut donc pas avoir de paramètre. MyDouble doit être de type MyDouble sans paramètre.
De même MyComplex ne doit pas avoir de paramètre.

Les deux doivent répondre à une interface commune pour addition, etc. Donc interface MyNumber, implémentée par les deux. Mais il va lui falloir un paramètre.

Parce que, pour l'addition, supposons que ça ressemble à ça :

Code :
1
2
3
public interface MyNumber {
  MyNumber add(MyNumber other);
}
Du coup MyDouble ressemblera à

Code :
1
2
3
4
5
6
public class MyDouble implements MyNumber {
  double value;
  MyDouble add(MyNumber other) {
    double newValue = this.value + other./* ? là on peut rien faire de MyNumber other*/;
  }
}
Ça ne va pas. MyDouble.add() doit prendre des MyDouble en paramètre et donner des MyDouble en sortie.

Comme ça :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface MyNumber<T extends MyNumber<T>> {
  T add(T other);
}
 
public class MyDouble implements MyNumber<MyDouble> {
  double value;
  MyDouble add(MyDouble other) {
    double newValue = this.value + other.value;
 
    MyDouble newDouble = new MyDouble();
    newDouble.value = newValue;
    return newDouble;
  }
}
Et voilà.

Pour les rendre comparables, ajouter :

Code :
1
2
3
public interface MyNumber<T extends MyNumber<T>> extends Comparable<T> {
  ...
}
__________________
Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher du poisson, il videra le lac et au bout de deux ans son village ne mangera plus jamais.
Partagez vos connaissances, mais aussi comment s'en servir.
thelvin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2013, 19h26   #3
<_oodTi96Tiboo_>
Candidat au titre de Membre du Club
 
Inscription : décembre 2006
Messages : 61
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : décembre 2006
Messages : 61
Points : 11
Points : 11
Bonsoir thelvin,

Je suis d'accord avec toi et je pense que ce que j'ai posté dans mon premier message répond à se que tu dis.

Toutefois, j'ai un problème lorsque je veux utiliser MyDouble et MyComplex dans une class utilisant le père de ses deux class (MyNumber<T>).

Soit le type "Type" qui extends "MyNumber<Type>"

pourquoi n'est il pas possible de faire ce qui suit?
Type a = new MyDouble();

Or MyDouble est bien du type MyNumber<T>
<_oodTi96Tiboo_> est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2013, 20h02   #4
adiGuba
Expert Confirmé Sénior
 
Avatar de adiGuba
 
Homme
Développeur Java/Web
Inscription : avril 2002
Messages : 12 655
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Corse (Corse)

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

Informations forums :
Inscription : avril 2002
Messages : 12 655
Points : 22 429
Points : 22 429
Salut,

Citation:
Envoyé par <_oodTi96Tiboo_> Voir le message
Soit le type "Type" qui extends "MyNumber<Type>"

pourquoi n'est il pas possible de faire ce qui suit?
Type a = new MyDouble();

Or MyDouble est bien du type MyNumber<T>
D'une part les normes de codages recommande d'utiliser une seule lettre en majuscule pour éviter les confusions. Bref tu devrais utiliser T à la place de Type.


Ensuite non ce n'est pas la même chose, justement parce que le type exact des paramètres paramétrés n'est pas connu lors de la compilation de ta classe.

Lorsque tu compiles ceci :
Code :
class Triedre<T extends MyNumber<T>> {
Tu sais que le type T étends MyNumber<T>, mais c'est tout. Tu ne peux pas en conclure autre chose ou lui attribuer un type fixe.

En effet lorsque tu associes un objet de type "MyDouble" dans un objet de type T, tu casses la généricité.

En effet cela marchera lorsque tu utiliseras un new Triedre<MyDouble>, mais que se passera-t-il lorsque tu instancieras un new Triedre<MyComplex> ?
En effet T devrait correspondre alors à MyComplex, mais tu met un MyDouble dedans ce qui est impossible puisqu'il s'agit d'un type parent.
C'est comme si tu écrivais ceci :
Code :
MyComplex m = new MyDouble(0);



Bref lorsque tu écris une classe générique, le type précis est inconnu et tu ne peux pas présumer qu'il s'agira d'un type précis. Sinon les generics sont inutiles...


a++
__________________
adiGuba [ tutoriels | blog | twitter ] Rédacteur/Modérateur Java Présentation de Java SE 7 (commentaires)
adiGuba est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/01/2013, 11h23   #5
<_oodTi96Tiboo_>
Candidat au titre de Membre du Club
 
Inscription : décembre 2006
Messages : 61
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : décembre 2006
Messages : 61
Points : 11
Points : 11
Bonjour AdiGuda,

Merci pour ta réponse. Elle confirme mes dernières recherches sur les génériques.

De ce fait, j'ai revu mon code hier soir. J'ai ajouté un constructeur à ma class abstract MyNumber prenant un "double" qui sera implémenté dans le class irritant de MyNumber:

Code :
1
2
3
4
5
6
7
8
9
 
public abstract class MyNumber<T> extends Number implements Numeric<T>{
 
public MyNumber(){
	this(0);
}
 
public MyNumber(double d) {}	// must be re-implemented by children
...
Toutefois lors que je tente d'utiliser ce constructeur dans la class "Triedre", on me dit qu'il n'est pas possible d'instancier le type "Type".

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Triedre<Type extends MyNumber<Type>>{
	private Type a;
	private Type b;
	private Type c;

	public Triedre(double a, double b, double c) {
		this.a = new Type(a);	// error : Cannot instantiate the type Type
		this.b = new Type(b);	// error : Cannot instantiate the type Type
		this.c = new Type(c);	// error : Cannot instantiate the type Type
	}
	...
}
Peux tu me dire pourquoi le construteur "MyNumber(double d)" n'est pas visible dans la class Triedre?

PS: Merci pour le rappel des conventions de nommage des generics. Si j'ai utiliser <Type> au le de <T> c’était pour vérifier qu'il n'y avait pas de confusion entre les différents type generic.
<_oodTi96Tiboo_> est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/01/2013, 11h43   #6
adiGuba
Expert Confirmé Sénior
 
Avatar de adiGuba
 
Homme
Développeur Java/Web
Inscription : avril 2002
Messages : 12 655
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Corse (Corse)

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

Informations forums :
Inscription : avril 2002
Messages : 12 655
Points : 22 429
Points : 22 429
Citation:
Envoyé par <_oodTi96Tiboo_> Voir le message
J'ai ajouté un constructeur à ma class abstract MyNumber prenant un "double" qui sera implémenté dans le class irritant de MyNumber:
Les constructeurs ne s'héritent pas, et ne peuvent donc pas être "implémenté" par des classes filles...


Citation:
Envoyé par <_oodTi96Tiboo_> Voir le message
Toutefois lors que je tente d'utiliser ce constructeur dans la class "Triedre", on me dit qu'il n'est pas possible d'instancier le type "Type".
Normal : le type "Type" n'existe pas !!!


En fait tu veux faire ceci :
Mais c'est quoi T ?
Cela peut être un MyDouble, un MyComplex... ou n'importe quelles autres classes héritant de MyNumber !
Le compilateur ne peut pas décider de cela à ta place !


Dis-toi bien qu'à l'intérieur du code d'une classe Generics, le type exact de T est inconnu. Donc le compilateur ne peut pas effectuer certaines opération comme new T() ou T.class...
(enfin en vrai il pourrait le faire, mais cela aboutirait à du code non-typesafe, ce qui va à l'encontre même des Generics)



Bref tu ne peux pas faire cela !
Soit tu fait quelque chose de fortement typé :
Code :
1
2
3
4
5
6
7
8
9
10
11
public class Triedre {
	private MyDouble a;
	private MyDouble b;
	private MyDouble c;
 
	public Triedre(double a, double b, double c) {
		this.a = new MyDouble(a);
		this.b = new MyDouble(b);
		this.c = new MyDouble(c);
	}
}
Soit tu fait quelque chose de complètement générique :
Code :
1
2
3
4
5
6
7
8
9
10
11
public class Triedre<T extends MyNumber<T>>{
	private T a;
	private T b;
	private T c;
 
	public Triedre(T a, T b, T c) {
		this.a = a;
		this.b = b;
		this.c = c;
	}
}
Mais tu ne peux pas faire les deux.


A la rigueur, tu peux te faire deux petite méthode factory pour simplifier la création de Triedre<MyDouble> ou Triedre<MyComplex> :
Code :
1
2
3
4
5
6
7
	public static Triedre<MyDouble> newDouble(double a, double b, double c) {
		return new Triedre<MyDouble>(new MyDouble(a), new MyDouble(b), new MyDouble(c));
	}
 
	public static Triedre<MyComplex> newComplex(double a, double b, double c) {
		return new Triedre<MyComplex>(new MyComplex(a), new MyComplex(b), new MyComplex(c));
	}


a++

PS : Tant que tu n'encapsules pas les classes il n'y a aucun conflit dans les noms des paramètres Generics. C'est au contraire le fait d'utiliser un nom de classe qui apporte de la confusion dans la lecture du code...
__________________
adiGuba [ tutoriels | blog | twitter ] Rédacteur/Modérateur Java Présentation de Java SE 7 (commentaires)
adiGuba est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/01/2013, 12h40   #7
<_oodTi96Tiboo_>
Candidat au titre de Membre du Club
 
Inscription : décembre 2006
Messages : 61
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : décembre 2006
Messages : 61
Points : 11
Points : 11
j'aurai une petite nuance à ta réponse. Mais peut être que j'ai mal compris un truc.

Je suis Ok sur le fait que "Type" n'est pas spécifiquement connu par la compilateur.

Mais le compilateur sait qu'il extends MyNumber non?

or si on déclare un constructeur dans MyNumber il doit pouvoir le voir non?
<_oodTi96Tiboo_> est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/01/2013, 12h47   #8
adiGuba
Expert Confirmé Sénior
 
Avatar de adiGuba
 
Homme
Développeur Java/Web
Inscription : avril 2002
Messages : 12 655
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Corse (Corse)

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

Informations forums :
Inscription : avril 2002
Messages : 12 655
Points : 22 429
Points : 22 429
Citation:
Envoyé par <_oodTi96Tiboo_> Voir le message
Mais le compilateur sait qu'il extends MyNumber non?
Oui, et c'est tout ce qu'il sait.
Du coup tu peux utiliser les méthodes définis dans MyNumber sur les objets de type T.

Citation:
Envoyé par <_oodTi96Tiboo_> Voir le message
or si on déclare un constructeur dans MyNumber il doit pouvoir le voir non?
Non : les constructeurs ne n’héritent pas...


a++
__________________
adiGuba [ tutoriels | blog | twitter ] Rédacteur/Modérateur Java Présentation de Java SE 7 (commentaires)
adiGuba est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/01/2013, 13h14   #9
<_oodTi96Tiboo_>
Candidat au titre de Membre du Club
 
Inscription : décembre 2006
Messages : 61
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : décembre 2006
Messages : 61
Points : 11
Points : 11
Oui effectivement j’oublie toujours ce fait.

Merci pour tes conseils. Je constate que tu est toujours aussi magnanime malgré les années. Bonne continuation.

Sébastien.
<_oodTi96Tiboo_> est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 18h11.


 
 
 
 
Partenaires

Hébergement Web