Généricité et héritage [Résolu] - Java - Programmation
Marsh Posté le 30-10-2009 à 10:06:14
C'est pas moche, c'est un upper cast. Tous les Lattice ne sont pas des IntervalLattice, il faut donc t'attendre à ce que la conversion échoue.
Marsh Posté le 30-10-2009 à 10:14:20
Salut Taz, et merci.
oui, je suis bien d'accord avec toi,
mais là, ce n'est pas n'importe quel lattice,
c'est un Lattice<IntervalPattern>.
Du coup, j'ai mal modélisé, car on a de la redondance et des cast,
mais je ne trouve pas moyen de l'éviter...
edit : je ne dis pas que les cast sont pas bien, je dis juste que j'aimerai m'en passer
Marsh Posté le 30-10-2009 à 14:49:10
Si dans ton code tu n'as qu'une seule variante de Lattice<IntervalPattern> qui est IntervalLattice, alors tu peux déclarer la variable l comme étant de type IntervalLattice, tu ne devras pas faire de cast!
Sinon comme dit Taz c'est que tu as plusieurs sortes de Lattice<IntervalPattern> avec lesquels tu travailles, dont l'une est IntervalLattice et là tu dois effectivement faire un cast si tu les mets toutes dans le même sac. Sinon tu peux toujours les stocker dans des collections différentes et utiliser des variables du type correspondant.
D'autre part si aucune classe qui implémente l'interface Lattice<E extends Pattern> (oui tu l'as déclarée comme classe abstraite mais tu devrais en faire une interface) ne déclare de méthode publique additionnelle ou qu'elle en déclare mais que tu ne les utilise pas dans la plupart des opérations, alors tu peux travailler directement dans ton code avec l'interface, c'est à dire avec des variables de type Lattice<IntervalPattern> et tu n'as aucun besoin de faire un cast sauf quand tu dois accéder à ces méthodes qui ne sont pas dans l'interface.
A part cela, c'est fou le nombre de personnes qui continuent à utiliser Vector.
Marsh Posté le 30-10-2009 à 16:42:41
Hello, et merci,
voici un exemple qui exhibe mieux mon problème
Code :
|
J'ai donc loupé quelque chose dans la généricité, et je ne trouve pas quoi...
Merci !
ps : un jour, j'avais fait un test débile avec Vector et ArrayList, remplir 1000000 objets et les supprimer, et dans mes souvenir le Vector était bien plus rapide. Tu suggères quoi ? (même si c'est pas l'objet du post )
Marsh Posté le 30-10-2009 à 22:11:27
Si la méthode renvoie un objet de type "E extends Pattern" alors pas besoin de cast, non?
Je n'ai pas une vue d'ensemble du projet alors difficile de t'aider plus.
On utilise normalement ArrayList à la place de Vector car il n'est pas synchronisé donc théoriquement plus rapide.
Marsh Posté le 30-10-2009 à 22:50:27
Bon, après relecture je pense que tu fais trop compliqué et tu n'as pas besoin de types génériques partout. Tu devrais faire ceci:
Transformer Pattern en une simple interface:
Code :
|
Interval implémente cette interface:
Code :
|
Pour la classe Lattice, ne pas utiliser des éléments de type "E extends Pattern" mais juste "Pattern" et travailler avec cette interface:
Code :
|
Marsh Posté le 01-11-2009 à 21:13:59
Merci pour ta réponse,
ok pour Pattern en interface, et pour les ArrayList.
Par contre, suivant le type de Pattern, je peux avoir le constructeur de la classe Lattice différent et l'implémentation de la méthode meet différente.
C'est pour ça que j'avais plus haut
Code :
|
c'est finalement ce que tu demandais dans ton premier message, que je n'avais pas compris à ce moment là.
Du coup, tu as bien raison, je fais trop compliqué et je mélange deux choses : héritage et généricité (d'où le titre du post)
et il est clair que ces deux là ne font pas bon ménage ensemble !
Pourquoi ce mélange ? Car je voulais forcer qu'on ne puisse mettre qu'un seul type de Pattern dans un Lattice, mais
que suivant le type de Pattern, la classe conteneur Lattice soit munie de constructeurs différents et possiblement de redéfinition et/ou d'ajout de méthodes.
Du coup, je suis assez déçu, ce que je veux faire n'est pas possible je pense (je me trompe peut être...)
Aussi, je vais revenir à du classique héritage, et quelques exceptions pour gérer le fait qu'on ne peut mettre qu'un type de Pattern
dans un lattice (en mettant un paramètre Class<?> patternClass dans le constructeur de Lattice par exemple ?) Finalement,
j'aurai deux hiérarchies parallèles : celle des Lattice, et celles des Pattern correspondants. Je ne sais pas trop encore ... J'y refléchis,
et merci en tout cas pour la discussion (qui n'est peut être pas close, je suis toujours ouvert à la critique).
ps : j'ai re-tester le tri de 10000000 Random Integer dans une ArrayList et dans un Vector ....
10 sec pour vector et 8.5 sec pour une arraylist, sur un 15 ène d'essais, je passe au ArrayList
Marsh Posté le 01-11-2009 à 23:57:59
OK, j'ai compris ce que tu essayes de faire: tu veux qu'une implémentation spécifique de Lattice utilise une implémentation spécifique de Pattern, tout en utilisant des interfaces communes.
C'est possible à réaliser mais c'est assez compliqué à écrire!
En fait tu dois paramétriser les interfaces Lattice ET Pattern pour ne pas avoir à faire de cast. Accroche-toi:
L'interface Pattern paramétrisée:
Code :
|
La classe IntervalPattern implémente cette interface:
Code :
|
Ensuite l'interface Lattice qui est paramétrisée pour utiliser des objets qui implémentent Pattern:
Code :
|
Et enfin la classe IntervalLattice qui est une implémentation de Lattice acceptant uniquement des objets de type IntervalPattern:
Code :
|
Et voilà, pas de cast et tout se tient. J'espère ne pas t'avoir donné mal de tête et te souhaite un bon travail.
Marsh Posté le 02-11-2009 à 14:41:38
J'ai écrit et tester ce que tu viens de me donner, et je dois dire que ...
ça marche très bien, et c'est même logique. Il est évident pour moi maintenant qu'il faille passer
par de l'interface. Par contre, j'avais tester des choses du genre Pattern<E extends Pattern<E>>
mais j'avais abandonné car je veux toujours un code strict zéro warning sans faire de @suppress
Là je n'ai pas le choix, et ça me va très bien comme ça. A problème sioux, solution sioux
Par contre, j'ai un petit soucis : j'ai besoin de faire des choses du genre :
Code :
|
et là, boom :
Citation : Type mismatch: cannot convert from ArrayList<IntervalLattice> to List<Lattice> |
Par contre, si je fais
Code :
|
alors ca marche très bien.
Forcément, j'ai le même problème avec les Pattern.
Code :
|
Ce n'est pas bien méchant, et je pense laisser dans l'état. Je suis juste maniaque des warning,
mais si tu vois une solution élégante, ca m'intéresse d'en discuter.
En tous les cas, je marque le post comme [résolu] et te remercie vivement pour ton attention
et le temps que tu as passé sur mon problème,
Au plaisir de se lire à nouveau
Marsh Posté le 02-11-2009 à 19:06:26
Il n'y a pas de warning avec la solution que je t'ai proposée je pense.
Effectivement tu dois faire comme tu l'as écrit: instancier des
Code :
|
si tu veux créer des une liste d'objets Lattice, pouvant contenir des IntervalLattice ou d'autres objets qui implémentent Lattice.
Par contre si tu veux créer une liste contenant uniquement des objets IntervalLattice, tu écris:
Code :
|
Donc, toujours spécifier le même type générique des deux côtés et il n'y a aucun problème.
Marsh Posté le 03-11-2009 à 02:28:44
Encore un petit détail: tu peux éventuellement utiliser une classe abstraite au lieu d'une interface si tu veux fournir des implémentations communes à toutes les classes qui l'"implémentent". Evidemment si la classe abstraite n'a aucune méthode implémentée, autant la transformer en interface d'où ma suggestion. Tu peux aussi combiner les 2: faire une interface puis une classe abstraite qui implémente partiellement l'interface et qui va être étendue par d'autres classes.
D'un point de vue conceptuel, une interface est une vue purement "publique" et "externe" sur un objet, et une classe abstraite est plutôt vue comme une aide à l'implémentation, permettant d'éviter la répétition de code commun. La différence majeure entre les deux est qu'en java, une classe peut implémenter plusieurs interfaces mais ne peut étendre qu'une seule classe (abstraite ou non).
Marsh Posté le 30-10-2009 à 09:44:42
Bonjour toutes, tous,
je suis confronté à un problème assez sioux que je vous expose ci dessous.
Considérons d'abord la classe abstraite suivante :
et la suivante :
J'utilise ces deux classes de cette manière :
et
Le problème avec ça est que je dois souvent faire des cast comme
et ça c'est très mal ... pas propre, très mal réutilisable, et finalement pas générique du tout.
en fait, je cherche un moyen de n'avoir qu'une seul entité pour Lattice<E> et "ELattice".
J'espère avoir énoncé le problème clairement,
n'hésitez à dire sinon,
un grand merci d'avance,
cordialement,
Message édité par Krukov le 02-11-2009 à 14:42:29