|
Publicité | |||||||||||||||||||||||
|
|
#1 | ||||
|
Membre habitué
![]() ![]() Inscription : janvier 2007 Messages : 324 ![]() |
Depuis une très longue période, le mot-clé const est marqué réservé par dans de nombreux éditeurs IDE Java, tels qu'Eclipse, qui le colorie comme un mot-clé réservé du langage même s'il en interdit l'emploi dans le même temps.
Le mot-clé const a un sens différent de final. Car si final appliqué à une variable ou variable membre protège une référence et interdit à son pointeur de désigner autre chose que cette variable, const est supposer protéger effectivement cette variable contre des modifications par, entre-autres, des fonctions membres modificatrices. C'est ainsi que dans ce code d'exemple, pourvu d'un mot-clé final, ce mot-clé ne protège pas le contenu de la variable sur laquelle il s'applique. Et par là, je trouve son usage d'un intérêt limité. Code :
C:\build\classes>java -cp . Essai Avant: Remulus Après: Rébus (en revanche, dans mon code source, je n'aurais pas pu écrire ceci: Code :
Alors, bien entendu, il existe le pattern immutable. Mais il pose un problème: il n'offre pas de garantie. Je peux par principe vous présenter une classe nommée TotoImmutable, et malheureusement, soit par oubli, soit par erreur, elle ne l'est pas réellement... Seul un mot-clé const, je crois, permettrait d'être réellement rassuré. Qu'en est-il de sa venue? Est-elle prévue? Dernière modification par grunt2000 ; 24/04/2007 à 16h41. |
||||
|
|
00
|
|
|
#2 |
|
Membre du Club
![]() Inscription : avril 2007 Messages : 120 ![]() |
je crois qu'elle est prevue
|
|
|
00
|
|
|
#3 | |
|
Membre Expert
![]() Inscription : février 2007 Messages : 2 356 ![]() |
Citation:
Cela dit, même si je ne suis pas sûr que le cas particulier des const soit très intéressant, j'aimerais, moi aussi, que le langage évolue vers une plus grande expressivité. Soit le pattern de immutable qui est, je pense, garanti dès l'instant que l'on en respecte les règles. Tu pourrais toujours me répondre que l'on peut toujours se tromper. Et que ce serait bien, que grâce à un mot clef le compilateur vérifie cette qualité, et tu aurais raison. En ce genre de cas je me fais une sorte de règle de nommage, et j'essaie de trouver un test à la mode JUnit. |
|
|
|
00
|
|
|
#4 |
![]() ![]() Inscription : novembre 2006 Messages : 4 934 ![]() |
bof, y a "static" voir "static final" pour faire la même chose...
|
|
|
00
|
|
|
#5 | ||||||||||||
|
Membre Expert
![]() Inscription : janvier 2005 Messages : 2 800 ![]() |
Après avoir lu ton post ce matin, j'y ai réfléchi en allant en cours, et pour moi ce concept de const n'est pas applicable.
En fait, 2 possibilités: - soit le const est un modifieur d'une variable, exactement comme final Il y a ici un gros problème, c'est que le mot-clé const s'applique à une variable (donc à une référence), alors que le concept (l'immutabilité) s'applique sur l'instance de l'objet. Ainsi, tu peux faire: Code :
Mais là cela pose des problèmes. Imagine tu as une méthode qui prend en paramètre une instance de type UnObjet. Déjà ce qui est passée est une copie de la référence, donc il faut que le compilateur sache que c'était une const. Mais admettons. Code :
Code :
Code :
Code :
Ceci est quand même très embêtant. De plus, si une variable est déclarée const, il serait impossible de créer un objet const sans l'affecter à une variable. Code :
new const UnObjet(); //pourquoi pas? pas terrible quand même... - soit const serait un modifieur de classe, pour faire par exemple: Ceci permettrait de vérifier l'immutabilité à la compilation. On se pose alors la question, comment vérifier l'immutabilité à la compilation? - il faut vérifier récursivement que les attributs de type primitifs sont finaux, et que les attributs références sont soit finaux, soit constants. Pour les finaux, c'est facile. Pour les constants, on a vu dans le premier point que const ne devait pas s'appliquer à une variable, donc il faudrait que la classe de chacun des attributs soit const (immutable). Or, avec le pattern immutable, on peut avoir des composants mutables tout en garantissant une classe immutable. par exemple: Code :
(en y réfléchissant, pourquoi pas) Voilà pourquoi je pense que ça ne serait finalement pas une avancée aussi intéressante qu'il n'y parait... Sans parler de la compatibilité ascendante, des classes qui sont immutables par le pattern, qui devraient être composées dans des classes "const" alors qu'elles ne sont elles-même pas const (bien qu'immutable). Pour prendre un peu de recul, si on introduit un mot-clé (du moins son utilisation, car il existe déjà sans être utilisé) pour un design-pattern, pourquoi ne pas introduire également d'autres mots-clés : singleton, listener... Code :
public singleton class MonSingleton { ... } |
||||||||||||
|
|
00
|
|
|
#6 | ||
|
Membre habitué
![]() ![]() Inscription : janvier 2007 Messages : 324 ![]() |
@gifftane: les choses sont exactement comme tu les dis. Le pattern immutable fonctionne très bien dès que l'on en respecte les règles. Mais toi recevant utilisant une classe "Immutable" dont tu ne sais rien de l'auteur ou du code, tu ne peux qu'espérer qu'elle est bonne.
Il existe un cas de figure, où sauf à me tromper lourdement (c'est possible!!!), l'emploi du const semble indispensable. Il s'agit des EJB Stateless Remote et Local. Lorsque j'ai décris ce point d'entrée de service dans un EJB Stateless: Code :
En revanche, si l'EJB a une interface Locale, l'appel est - sauf mauvaise interprétation de ma part - direct. Les n couches de marshalling et unmarshalling disparaissent, et l'on a affaire à un appel Java classique, normal, où le paramètre cmd est cette fois passé par référence. Et par là, s'il est modifié dans la méthode valider, il sera restitué modifié à l'appelant. En passant Remote à Local, nous provoquons un changement de comportement potentiel dans notre application, aux effets de bords inattendus. Mais comment envisager sur cent, deux cents, cinq cents points d'entrée de service que nous aurions écrits ceux succeptibles de nous gêner, en mode Local? En mettant les paramètres d'entrées des services const, pour déclarer qu'au sein des méthodes EJB Stateless nous entendons bien ne pas les modifier, et demander au compilateur de vérifier ce fait. @om: Le mot-clé const existe et fonctionne. Il est implémenté en C++, et peut-être dans d'autres langages. Cela dit, const impose l'usage de règles comme tu l'as pensé. Par exemple, un objet const ne peut être passé qu'au travers d'une fonction annoncée const (c'est à dire ne modifiant pas l'objet this auquel elle va s'appliquer), ainsi que quelques autres règles. |
||
|
|
00
|
|
|
#7 |
|
Membre Expert
![]() Inscription : février 2007 Messages : 2 356 ![]() |
Même s'il n'y a rien pour garantir l'immutabilité (dont il resterait à établir la relation avec const, je ne sais pas exactement comment notre ami à l'origine du post voit les choses), tu peux jouer avec le mot clef final.
Si ce terme ne garanti pas la constance de ses composants, il garanti au moins la constance de lui même, ce qui est déjà bien ! Pour les composants tu peux aussi leur affecter un final, pour les composants des composants aussi, etc. Tu peux régler ainsi le coté immuable d'un objet, mais jamais garantir sur la totalité. Mais moi je trouve que c'est déjà bien et intéressant. |
|
|
00
|
|
|
#8 | |||
![]() ![]() Développeur Java/Web Inscription : avril 2002 Messages : 12 293 ![]() |
Salut,
Citation:
Citation:
Citation:
static permet de déclarer des attributs ou des méthodes de classes (au lieu d'instance). final permet soit d'empêcher de redéfinir une méthode, soit d'empêcher de modifier la valeur d'une variable. Mais pour un objet cela empêche seulement de modifier la valeur de la référence, et le contenu de l'objet reste modifiable via ses mutateurs... Le const du C++ est différent :
Ce mot-clef permet, couplé avec le passage de référence, d'éviter de multiples copies d'objets inutile... Dès le début Java a adopté une autre approche, en se basant sur les classes immuables... Enfin je ne suis pas sûr que l'intégration du mot clef const soit évidente :
a++ PS : avant de poster je viens de voir qu'il y a eu plusieurs autres posts : ®om |
|||
|
00
|
|
|
#9 | ||||
|
Membre habitué
![]() ![]() Inscription : janvier 2007 Messages : 324 ![]() |
Avec const, mon programme deviendrait ceci:
Code :
Code :
Intérêt? Cela évite de créer une classe immutable, qui oblige: - à créer une classe, PersonneImmutable, compagnone de Personne, et reprenant tous ses getters. - soit à procéder par copie d'objet à l'intérieur de cette classe immutable, mais alors on a une consommation de temps, de mémoire, et le risque - toujours - d'avoir fait... une mauvaise méthode clone ou d'avoir fait un new Personne() mais en oubliant de recopier la totalité des valeurs de ses membres qui seraient utiles. - soit de définir l'immutabilité de la Personne comme une interface Immutable interne à la classe Personne, et qui ne reprend que les getters. Mais alors on perd les éventuels héritages et implémentations de Personne lorsque l'on retourne une PersonneImmutable. A mes yeux, donc, const est nettement plus élégant. Plus propre. @adiGuba: Enfin je ne suis pas sûr que l'intégration du mot clef const soit évidente : Soit les classes l'API standard sont modifiées afin de l'utiliser, et dans ce cas on peut se retrouver avec un grand nombre d'incompatibilitée (que se passerait-il si je redéfinit une méthode const sans respecter son "contrat" ?). Je ne pense pas que la redéfinition d'une méthode permettrait d'oublier son mot-clé. Il suffit d'écrire le compilateur et la JVM d'une manière qui convient. Soit les classes de l'API ne l'utilisent pas, et dans ce cas il perdrait beaucoup de son intérêt... Il faut effectivement repasser sur toutes les APIs, mais en limitant cependant son action aux prototypes des fonctions dans la majorité des cas. C'est un travail certainement fastidieux pour Sun, mais à tout prendre, je pense, moins que celui d'avoir mis en place les génériques. Dernière modification par grunt2000 ; 25/04/2007 à 11h16. |
||||
|
|
00
|
|
|
#10 | |
|
Membre Expert
![]() Inscription : janvier 2005 Messages : 2 800 ![]() |
Citation:
il faut faire 2 méthode: print(String) et print(const String)... ça double pas mal de méthodes... Et une méthode qui renvoie un String, il faudrait définir si ce que ça renvoie c'est un const ou pas: et (il ne serait pas possible de le déterminer à la récupération, car on ne peut pas affecter un const à un non const et vice-versa - cf mon premier post-).
__________________
®om's blog http://rom.developpez.com Piratage ou usage commun ? Comprendre le mystère de l'argent et le problème des intérêts manquants Dernière modification par ®om ; 25/04/2007 à 11h54. |
|
|
|
00
|
|
|
#11 | |||
|
Membre Expert
![]() Inscription : février 2007 Messages : 2 356 ![]() |
Citation:
(je commente les points importants dans le commentaire, soyez compréhensifs). Code :
Mais on a eu peur.
|
|||
|
|
00
|
|
|
#12 | ||
|
Membre habitué
![]() ![]() Inscription : janvier 2007 Messages : 324 ![]() |
Oui, mais comment pourrais-tu alors utiliser deux instances de ta personne, l'une modifiable et l'autre non?
Car ce que je veux me permettre de faire, c'est ceci, à partir d'une unique définition de classe. Code :
sera possible. mais sera interdit. Dernière modification par Ricky81 ; 05/05/2007 à 15h33. |
||
|
|
00
|
|
|
#13 | |||
![]() ![]() Développeur Java/Web Inscription : avril 2002 Messages : 12 293 ![]() |
Citation:
Il s'agit juste d'une approche différente du même problème (mais je ne dis pas qu'une est meilleure que l'autre). Citation:
Logiquement le compilateur interdit d'appeler des méthodes non-const depuis des méthodes const... Prenons l'exemple de HashMap. On est d'accord qu'un grand nombre de ses méthodes devraient être const (isEmpty(), size(), etc...), alors que d'autres ne le devraient pas (add(), remove(), etc...). Or, afin de gérer un cache, j'ai justement une classe qui hérite de HashMap et qui revérifie la validité de la Map avant chaque action. Donc le méthode isEmpty() peut aboutir à une modification de ma Map... et donc elle casserait le principe du const et donc mon code ne compilerait plus... Citation:
Mais surtout les Generics conservent la compatibilité a++ |
|||
|
00
|
|
|
#14 | |||
|
Membre Expert
![]() Inscription : janvier 2005 Messages : 2 800 ![]() |
Citation:
Code :
|
|||
|
|
00
|
|
|
#15 |
|
Membre habitué
![]() ![]() Inscription : janvier 2007 Messages : 324 ![]() |
Non, ne t'inquiètes pas. L'affectation p1 = p2 est interdite également.
Tu ne peux pas affecter un objet constant à une référence se déclarant porteuse d'un objet non constant. |
|
|
00
|
|
|
#16 | |||
|
Membre Expert
![]() Inscription : janvier 2005 Messages : 2 800 ![]() |
Citation:
Donc const Personne n'est pas compatible avec Personne. Donc si tu as une méthode, faisons simple: Code :
public static void afficher(Personne personne) {...} Code :
|
|||
|
|
00
|
|
|
#17 |
|
Membre habitué
![]() ![]() Inscription : janvier 2007 Messages : 324 ![]() |
Non, l'inverse n'est pas vrai.
avec: const X a; X b; Il t'est 'interdit d'écrire: b = a; // Violation de la constance de a. mais pas: a = b; Tu peux affecter un objet non const à un pointeur const. Mais à travers ce pointeur const, tu ne pourras plus jamais le modifier. Ce lien parle du "const-correctness" dans les langages: http://en.wikipedia.org/wiki/Const. Voir la section final in Java en particulier. Ils ont l'air plus pessimistes sur son implémentation future. |
|
|
00
|
|
|
#18 | |||
|
Membre Expert
![]() Inscription : janvier 2005 Messages : 2 800 ![]() |
Citation:
Le premier sens je l'ai montré dans le post précédent. Le second sens (il suffit d'inverser le sens d'affectation): Code :
|
|||
|
|
00
|
|
|
#19 | ||
|
Membre habitué
![]() ![]() Inscription : janvier 2007 Messages : 324 ![]() |
Oui, absolument!
Code :
Il n'y a pas de magie dans ce cas-là: aucun moyen de l'éviter... En revanche, en manipulant p2 tu ne pourras rien modifier. C'est comme si je te donne un accès en lecture à mon compte en banque. Tu ne peux pas verser ou retirer de l'argent dessus. Mais si moi, dans le même temps, je conserve une autre référence dessus - elle modifiable - et que j'y mets ou que j'en retire de l'argent, eh bien nécessairement, tu verras les sommes évoluer dessus... alors que tu as un pointeur const! Mais l'important pour moi, c'aura été qu'en te donnant un accès const à mon compte en banque je serai sûr que toi tu ne pourras pas le modifier! const, ce n'est pas forcément la garantie qu'un objet garde la même valeur (ce serait trop complexe à vérifier), c'est garantir que l'on ne peut pas, soi, le modifier dans un certain périmètre. Dernière modification par Ricky81 ; 05/05/2007 à 15h34. |
||
|
|
00
|
|
|
#20 | |||||||
![]() ![]() Développeur Java/Web Inscription : avril 2002 Messages : 12 293 ![]() |
Citation:
Et en même temps une simple interface peut amplement suffire pour "simuler" le const, par exemple dans ton cas : Code :
Code :
Code :
|
|||||||
|
00
|
Copyright © 2000-2012 - www.developpez.com