Deux enums, bien évidemment différents.
Une fonction (de classe) générique qui va attacher chaque enum à sa combobox (GXT) (entre autres multiples choses), et qui va aussi vouloir avoir accès à la fonction values() générée à la volée par le compilo (?) et qui n'appartient bien évidement pas à la classe Enum<> (ce qui se comprend pour une fonction static finale).
Finalement, je m'en suis sorti en passant le résultat de la fonction values() à ma fonction au lieu de laisser la fonction obtenir toute seule ce dont elle avait besoin des enums.
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Quelque chose comme cela ?
Mais je t'accorde qu'une méthode static Enum.values(Class<Enum>) aurait été plus pratique
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 public static <T extends Enum<T>> void method(Enum<T> uneValeur) { T[] values = uneValeur.getDeclaringClass().getEnumConstants(); System.out.println("uneValeur : " + uneValeur); System.out.println("values : " + Arrays.toString(values) ); }
a++
C'est à peine différent de ce que j'ai fait. L'idéal étant de ne passer aucune valeur à la fonction, et de se contenter de spécifier le type de l'énuméré à la classe (dans mon cas) générique.
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Ah ok je comprend ce que tu veux dire. Le problème vient de la perte du typeage des Generics. Tu peux t'en sortir en utilisant la classe en paramètre :
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 public class MaClass<T extends Enum<T>> { private final Class<T> enumType; public MaClass(Class<T> enumType) { this.enumType = enumType; } public T[] values() { return this.enumType.getEnumConstants(); }
Mais le problème vient surtout de l'approche radicalement différente entre les templates et les Generics
a++
PS : Au passage par curiosité : il est possible en C++ d'obtenir toutes les valeurs d'une enum ??? Car cela ne me semble pas faisable...
Moyennant feinte, cela se fait très bien -- après la situation sera un peu plus rose en C++0x si mes souvenirs sont bons.
Voilà une façon de faire, parmi d'autres possibles.
Code C++ : 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 struct MyEnum { enum type { FIRST, toto = FIRST, titi, tutu, LAST }; static char const* toString(type i) { char const* k_values[] = {"To to", "Ti ti", "Tu tu"}; STATIC_ASSERT(array_size(k_values)==LAST, Sizes_mismatch); assert(i>=FIRST && i <LAST && "out of range"); return k_values[i] } static type next(type e) { return type(e+1); } }; template <typename MyEnum> printAll() { for (MyEnum::type e=MyEnum::FIRST ; e!=MyEnum::LAST ; e=MyEnum::next(e)) cout << MyEnum::toString(e) << "\n"; } ... // l'appel qui ne me fait pas me répéter 3 fois: printAll<MyEnum>();
La production de l'énum demande un peu d'huile de coude qui se résout très bien avec un fichier squelette ou une phase de préprocessing.
Ce qui revient exactement à ce qui avait été dit : chacun ses habitudes et ses réflexes qu'il faut impérativement adapter.
Sinon, pour le code Java, Là j'ai l'impression que j'économise juste le passage du values() en paramètre pour quoi d'autre ? un .class ?
?
Code Java : Sélectionner tout - Visualiser dans une fenêtre à part MyFantasticToolBar<MyEnum1> tb = new MyFantasticToolBar<MyEnum1>(MyEnum1.class)
(Déjà que je souffre à taper les " = new LeTypeQueJeCopieColle" (j'ai un peu de mal avec eclipse sous macbookpro))
Mais ... est-on obligés de passer le enumType en paramètre ? Ne peut-on pas se contenter d'un
histoire de simplifier le code appelant ?
Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 public class MaClass<T extends Enum<T>> { public MaClass() { final Class<T> enumType = new Class<T>(); final T[] values = enumType.getEnumConstants(); } }
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Non car le type T ne peut pas être connu à l'exécution : les Generics n'effectue pas de duplication de code et ne sont pas fortement typé à l'exécution. Du coup impossible de faire des new T() ou autre sans se trainer le type Class correspondant.
Par contre cela a d'autres avantages comme la covariance. Avec ceci :
On peut afficher tous les éléments de n'importe quel enum tout simplement :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 public static <T extends Enum<T>> void printAll(Class<T> enumType) { for (T value : enumType.getEnumConstants()) { System.out.println(value); } }
a++
Code : Sélectionner tout - Visualiser dans une fenêtre à part printAll(MyEnum.class);
- Le constructeur de Class n'est pas visible. Donc on ne peut pas comme ça.
- On ne peut pas faire non plus T.class
- On ne peut pas faire non plus new T().getClass() car malheureusement et contrairement à C++ (je crois), on n'a pas le droit au new T();
Bertrand Meyer explique à la page 318 de CPOO pourquoi la création d'un générique de cette manière est illégale car on ne sait rien des procédures de création du type T. Perso, j'aurai voulu que la jre essaye avec le constructeur vide quitte à ce qu'elle me balance une exception.
Bref, si vous avez d'autres idées ...
Tout le monde savait que c'était impossible. Il est venu un imbécile qui ne le savait pas et qui l'a fait. Marcel PAGNOL
On ne savait pas que c'était impossible, alors on l'a fait. John Fitzgerald KENNEDY.
L'inexpérience est ce qui permet à la jeunesse d'accomplir ce que la vieillesse sait impossible. Paul (Tristant) BERNARD
La meilleure façon de prédire l'avenir, c'est de l'inventer.
Suite au manque que je relève dans mon message précédent, j'ai fait quelques essais...
J'avais dans l'idée de faire un truc similaire à String.class.newInstance() ) mais je ne peux pas faire T.class.newInstance() pour feinter leur interdiction de faire un new T()
Je n'ai pas regardé le fonctionnement interne des generics en Java alors je joue au naif ...
Si c'est un remplacement à la compilation, pourquoi il remplace pas mon T.class par String.class si mon T vaut String ? Il le fait bien pour le retour des méthodes ? non ?
On va me répondre que tout ce décide à l'exécution ...
Mais alors, pourquoi je peux faire :
avec
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 List l = createInstance(ArrayList.class); l.add("i"); System.out.println(l);
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 @SuppressWarnings("unchecked") protected <T extends Object> T createInstance(Class<T> t) { try { return (T) Class.forName(t.getName()).newInstance(); } catch (Exception e) { // Je conçois bien que pour certains types, le constructeur // ne soit pas visible mais je l'assume e.printStackTrace(); return null; } }
Bon, j'admets, c'est un peu violent
L'introspection, c'est bien a l'exécution et il le connait bien mon type !
Je suis perplexe ... Qu'est ce que j'ai loupé ?
Tout le monde savait que c'était impossible. Il est venu un imbécile qui ne le savait pas et qui l'a fait. Marcel PAGNOL
On ne savait pas que c'était impossible, alors on l'a fait. John Fitzgerald KENNEDY.
L'inexpérience est ce qui permet à la jeunesse d'accomplir ce que la vieillesse sait impossible. Paul (Tristant) BERNARD
La meilleure façon de prédire l'avenir, c'est de l'inventer.
Personne n'a cité la const correctness du c++ sur ce thread?
Non : contrairement aux Templates du C++n les Generics n'effectuent pas pas de remplacement à la compilation. Les Generics effectuent une vérification de la cohérence du typage à la compilation afin de t'assurer un code sécurisé (pas de ClassCastException), mais réutilisent à l'exécution le même code !
Tu est obligé d'utiliser un paramètre de type Class pour pouvoir faire cela, et de passer par la reflection. Dans ce cas à l'exécution tu peux connaitre le type du paramétrage.
D'ailleurs tu pourrais écrire directement ceci :
Il n'y a plus besoin de SuppressWarning car le typeage est sécurisé par les Generics
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 protected <T extends Object> T createInstance(Class<T> t) { try { return t.newInstance(); } catch (Exception e) { return null; } }
Les Generics ne sont pas des Templates comme les autres !
a++
Merci adiGuba pour ces éclaircissements.
En effet, je me suis rendu compte par la suite que je passais la classe, donc dans une class templaté qui voudrait créer un objet du type templaté, on devrait avoir quand même :
new MaClass<ArrayList>(ArrayList.class);
Mon dieu que c'est laid !
Tout le monde savait que c'était impossible. Il est venu un imbécile qui ne le savait pas et qui l'a fait. Marcel PAGNOL
On ne savait pas que c'était impossible, alors on l'a fait. John Fitzgerald KENNEDY.
L'inexpérience est ce qui permet à la jeunesse d'accomplir ce que la vieillesse sait impossible. Paul (Tristant) BERNARD
La meilleure façon de prédire l'avenir, c'est de l'inventer.
C'est un préjugé. J'ai vu des développeurs C++ débuter la programmation 3D en se servant d'un moteur 3D complet au lieu de passer par une API de bas niveau. N'étant pas statisticien, je ne m'avancerai pas sur leur nombre.
De plus, à ma connaissance, il n'y a pas de cursus scolaire (en France) où on ne fait que du Java sans avoir un minimum de base en algorithmique, je pense notamment aux cursus universitaires au sens large (licence générale d'informatique, DUT).
Je suis d'accord, je pense notamment à un benchmark OpenGL écrit en Java avec un Thread.sleep(long millis) qui n'avait rien à faire là alors que ça aurait eu un sens en C/C++ dans ce cas de figure.
La présence des pointeurs avec une grande liberté dans leur arithmétique est un obstacle à certaines optimisations de gestion de la mémoire au niveau du compilateur en C++, obstacle levé de fait en Java selon Brian Goetz.
Dernière modification par Invité ; 15/09/2009 à 10h47.
Ce n'est pas un préjugé, je n'ai pas cherché a généraliser (loin de moi cette idée), j'ai simplement parlé de connaissances personnelles qui ont tendance à empiler des framework pour faire des trucs relativement simple à la base uniquement parce que c'est tendance. heureusement pour moi d'autres sont plus pragmatiques et ont tendance à tempérer ces derniers.
Ensuite personnellement je ne me lancerai pas dans de la programmation 3D sans avoir un minimum étudié les concepts qui sont derrières et ce quelque soit le langage que je devrais utiliser derrière.
heureusement qu'il ne font pas que du java, sinon j'aurais peur.De plus, à ma connaissance, il n'y a pas de cursus scolaire (en France) où on ne fait que du Java sans avoir un minimum de base en algorithmique, je pense notamment aux cursus universitaires au sens large (licence générale d'informatique, DUT).
Cependant certains façon de faire en algorithme passe mieux dans certains langage que d'autres.
bazar: http://www.improetcompagnie.com/publ...ctacles-6.html
BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil
Emacs Wiki: http://www.emacswiki.org/
En attente de ce que produira: http://www.pushmid.com
Pour bosser sur les deux :
- Java rajoute 20% de productivité (environ). La lib Java permet de toujours retrouver ses petits quand on débarque sur un nouveau projet.
- C++ rajoute un paquet de performances. C++ est plus propre, parce que plus violent (Java encourage un peu trop facilement les erreurs silencieuses, quand C++ crashe directement).
Porter du code C++ est largement possible (et pas fondamentalement dur). Perso, ça m'a pris une semaine pour porter une appli full windows/VC++ vers du Linux/GCC, essentiellement parce que je ne savais pas comment faire quand j'ai commencé. Mieux vaut juste le faire avant que la taille du projet rende la chose atroce.
Pour moi, la plus grosse différence entre les deux langages (au delà des questions de lib, faire de la 3D en Java étant plutôt ardu) est le garbage collector. Sur une appli temps réel, c'est en général ingérable d'avoir des blocages imprévisibles pouvant monter à la seconde. Sur une appli sans trop de grosses contraintes à l'exécution, alors, je choisirai Java sans me poser de questions.
J'ai souvent vu ça :
Le gros avantage étant que ça marche, va juste y avoir un traitement d'ignoré, basiquement, un message client->serveur non traité, ou un click souris d'annulé, mais ça ne mets pas toujours en danger la stabilité du soft.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 while (true) { try { // Ma boucle principale } catch (Exception e) log e; }
Par contre... ça encourage à ne pas corriger l'erreur si celle ci ne génère aucun effet visible et que son taux de reproduction est minime. Le résultat étant que toutes les prochaines erreurs deviennent silencieuses, en ce sens qu'elles génèrent le même log. Et y a un moment ou le soft devient ingérable.
En C++, pas de try catch (au delà de ceux que tu génères toi même) et donc, pas de récupération d'erreur comme celle ci.
Après, ça peut passer pour un défaut de conception, même si dans certains cas je le pronerai (sur un serveur, c'est même un raccourci génial, tu sais que si un traitement plante bizarrement, ton serveur continue de tourner). Mais il faut derrière absolument que les dévs corrigent l'intégralité des bugs générés, et ça, c'est pas toujours donné.
Hein?
Il y a surtout un moment où le développeur doit se remettre en question. Dans ma boîte, le type qui écrit un catch(Exception) sans une très bonne raison est assuré de passer par la case goudron et plumes.
Tu peux pas mettre des lacunes aussi évidentes de gestion d'erreur sur le dos d'un langage. Dans ce cas que tu montres, ce n'est même pas un truc subtil qu'on pourrait faire sans faire gaffe, mais une faute de conception grossière.
Depuis quand le but d'une gestion d'exception est de laisser continuer l'application coûte que coûte dans un état indéfini et potentiellement instable? Le but d'une exception n'est pas de jeter sous le tapis des erreurs potentiellement graves pour donner un faux sentiment de stabilité.
Franchement je peux pas être d'accord avec ton point de vue. Et je maintiens que catcher une exception au hasard sans être sûr de pouvoir la gérer tient du vice.
En fait je vais te le dire, ne le prends pas mal mais à mon avis, comme beaucoup de développeur, tu ignores comment les exceptions doivent s'utiliser.
Oui en java il y a 2 types d'exceptions : les checked exceptions et les unchecked exceptions.
Les checked on est obligé de les catcher et de prévoir un traitement, les unchecked sont sensé ne pas arriver et donc il n'est pas obligatoire de prévoir un traitement.
Si une exception n'est pas catchée par l'appelant de la méthode qui l'envoie, il faut signaler qu'elle sera envoyée au dessus. Ainsi on est sur qu'elle sera traitée à un moment ou à un autre (choisi par le développeur).
Ce genre de boucle peut paraître idiote, mais si on ne sait pas comment est le reste du programme on ne peut rien en déduire.
Si c'est un serveur, l'important est qu'en toute circonstance ce dernier fonctionne et ne plante pas totalement au premier imprévu.
Après dans les logs de ton catch tu traces suffisamment pour être capable de savoir ce qui s'est passé et corriger le bug.
Sachant qu'en principe ce genre de catch ne doit attraper que les unchecked exceptions (NullPointerException par exemple que l'on ne doit jamais catcher car si elles arrivent il s'agit d'un bug), OutOfMemoryError en cas de dépassement mémoire, ce qui peut arriver sans que ce soit un bug).
En tout cas il vaut mieux que le programme retombe sur ses pieds si possible plutôt que le planter totalement.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager