La question est simple:
Comment declare vous vos variables d'instances?
(private or protected)
Version imprimable
La question est simple:
Comment declare vous vos variables d'instances?
(private or protected)
Si la classe n'est pas vouée à etre étendue :
Tout en private sauf les constantes de classe ( public static final MA_CONSTANTE=...)
Si la classe est vouée à être étendue :
Tout en protected SAUF les variables gérées exclusivement par la classe courante.
Oui mais coment tu fais pour savoir si une classe va etre etendu ou pas. Comment tu sais si une variable vas etre exclusivement utilise dans une class?
Bah ça, c'est toi qui décide lors de la conception : la classe que tu es en train de concevoir devra-t-elle uniquement être utilisée telle-quelle, ou bien le développeur suivant aura-t-il le droit d'étendre ta classe ? ça relève du problème de conception là.Citation:
Oui mais coment tu fais pour savoir si une classe va etre etendu ou pas
exemple assez courant :Citation:
Comment tu sais si une variable vas etre exclusivement utilise dans une class
Ta classe possède une variable privée qui lui sert par exemple de limite :
private int limite;
Cette limite peut être initialisée par une valeur par défaut que les classes fille auront le droit d'étendre :
protected static int DEFAULT_LIMITE=100;
l'affectation de la variable limite se fait forcément par un setteur puisque des traitements dans ta classe en découlent :
public void setLimite(int l){
this.limite=l;
... // traitement interne à ta classe
}
Si tu avais mis la variable "limite" en protected, rien n'empêchait la classe fille de la modifier directement en omettant de faire les traitements internes.
Pour conclure, il me semble que tout cela concernce les règles de conception de la POO.
salut,
le private interdit tout accès aux attributs d'une classe depuis l'extérieur (notion d'encapsulation) mais elle crée un problème au niveau de l'héritage si tu déclare les attributs en private les classes héritants ne pourront pas accéder à ces attributs alors pour ne pas être obligés de les déclarer comme public pour les utiliser on a pensés à protected qui permet à ces classes d'accéder à ces attributs.
Personnellement je déclare exclusivement mes attributs de classes en protected, le private me semblant trop restrictif :
- Impossibilité d'y accéder depuis l'extérieur, quelle que soit la classe appelante (en revanche un attribut protected peut être modifié depuis une classe appartenant au même package),
- Pour pouvoir modifier ou accéder à un attribut, méthodes get/set systématiques (contraignat quand il y a une vingtaine d'attributs),
- Voir plus haut.
Les attributs déclarés en private peuvent être, selon certains, pour éviter au développeur suivant de faire n'importe quoi. Mais je considère que c'est au développeur suivant de savoir ce qu'il fait.
Là, je ne suis pas du tout d'accord :Citation:
Envoyé par Rayndell
Quel est l'interet de déclarer un champ qu'on utilise exclusivemnt dans la classe courante comme protected ? aucun, et pire encore, c'est une source d'erreurs : les classes filles peuvent le changer par inadvertance (C'est parfaitemnt possible : à la longue, il y'aurait des collisions dans les noms de champs), et là, welcome to hell !
Pourquoi voudrais tu avoir des collisions de noms. Si tu veux utiliser une variable qui s'appèle comme celle definie dans la super classe alors c'est surement que c'est elle même que tu veux utilisé. Ou bien tu as un defaut de conception...Citation:
Envoyé par djo.mos
Oui mais tu peux decider pour le present mais jamais pour l'avenir. Imagine un jour on embauche une autre personne. Elle ne seras pas forcement au courant de ton design original.Citation:
Envoyé par iohack
Comment tu fais si un jour tu as une sous classe qui est obligé de faire un autre traitement?Citation:
Envoyé par iohack
Non, ce que je voulais dire est que si un champ X est déclaré protected dans la classe A et qu'il est pourtant destiné à être utilisé uniquement dans A, alors il sera disponible quand même dans les sous classes de A, ce qui est risque d'erreurs.
Un exemple :
C'est un exemple bidon : La connerie dans b est que le programmeur a pensé qu'il affectait 0 à la vraible locale de la méthode qu'il a utilisé dans le for, pourtant, c'est le champ A.idx qui est mis à 0. A partir de là, Dieu seul sait ce qui peut se passer ...Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 public class A { protected int idx; : : } public class B extends A { public void uneGrosseConnerie(){ for(int idx=0;idx<10;i++){ : : } idx = 0;//voici la connerie : : } }
Si idx etait déclaré private, on aura eu une erreur de compilation au lieu d'un maudit bug !
Choisir le meme nom de variable de boucle que de variable d'instance est tres maladroit.Citation:
Envoyé par djo.mos
Pour ma part se serais tres rare que j'utilise un nom de variable d'instance aussi court. idx. Je prefere largement index.
De plus si on a des bons outils de debug ce n'est pas difficile de corriger ce genre de bug.
Il est aussi rare de faire une l'erreur que tu as montrer. Ou alors tu n'as rien ecouté de ce que l'on t'as dis en cour et tu sais pas comment sont scopés les variables.
D'où l'importance de documenter son code (commentaires, diagramme des classes, etc).Citation:
Envoyé par mathk
Personnellement je partage l'avis de iohack. C'est à toi de savoir (décider) si la classe peut-être étendue ou pas.
Si non :arrow: déclarer la classe final, pas d'attribut protected.
Si oui, c'est à toi de considérer tous les problèmes qui peuvent en découler (même les plus impropables).
Voici dans ce cas un exemple un peu équivalent à celui de djo.mos.
Supposons que j'écrive les classe A et B. La classe B aurait besoin d'utiliser la méthode check de A. Supposons que B puisse encore être dérivé pour d'autres classes à nous que je n'ai pas écrite, on interdirait donc pas check d'être redéfinie.
Supposons à présent qu'un autre programmeur, qui n'a uniquement la documentation des méthodes public (ce qui n'est pas forcement dénué de sens car on ne souhaite pas forcement que les gens connaissent notre implémentation) redéfinisse la méthode check :
Et on a une lançée d'exception.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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 /** * @(#)Test.java * * Test application * * @author * @version 1.00 2007/6/23 */ import java.util.List; import java.util.ArrayList; import java.lang.IllegalArgumentException; class A { protected boolean check(int i) { return(i>=0); } public A(int i) { if(!check(i)) throw new IllegalArgumentException(); } } class B extends A { public B() { super(3); } public int autremethode(int i) { if(check(i)) return i; else return -i; } } class C extends B { protected boolean check(int i) { return(i<0); } public C() { super(); } } public class Test { public static void main(String[] args) { B b = new C(); } }
Oui mais l'utilisateur a eu besoin d'exprimer un autre implementation de check. C'est donc qu'il veux que i soit inferieur a zero. Si tu mets la method check private c'est pire qu'une exception car on peut meme pas exprimer d'autre besoins. Il faudra alors faire pleins de duplication de code.Citation:
Envoyé par millie
Je ne doute pas qu'il ai des cas ou private est utilile. Mais franchement je pense que private est trops souvant utilise, cela au depend de la reutilisation.
Dans ton exemple il sufira de faire dans C
Code:
1
2
3 public C { super(-3); }
Dans un monde ideal oui mais la programation c'est pas un truc de devinette. On jou pas au poker. :mrgreen:Citation:
Envoyé par le y@m's
Et puis les languages tell que Java sont si complexe que c'est encor plus difficile de tous prevoir.
Citation:
Envoyé par mathk
Non, car j'ai supposé que la personne utilisant la bibliothèque contenant les classes A et B n'avaient aucune idée de l'implémentation de ces classes (donc qu'il ne savait pas que A avait une méthode protegée check).
Donc, qu'il définisse check dans C sans avoir du tout la connaissance que cette méthode existait dans A.
Ce qui n'est pas si anodin que ça je pense, car, quand on dispose d'une hiérarchie très compliqué dans une bibliothèque, l'utilisateur de celle ci ne va pas forcement aller chercher la documentation de toutes les classes de la hiérarchie (et surtout des membres protegés dont il se moque en règle général).
Cet exemple donne un exemple, où le développeur n'a pas de chance car il va interferer dans le fonctionnement de A sans le savoir (a priori).
Mais évidemment, si je développe les 3 classes, je saurais comment ça marche et je ne me ferais pas avoir dans la classe C.
Salut,
Je vais ajouter mon grain de sel :)
Je suis tout à fait d'accord avec iohack et pas du tout avec mathk .
Il n'y a pas que la question des bugs. Le travail en équipe nécessite une "norme de codage", il nécessite également une bonne communication et la FORMATION des nouveaux (via une documentation de la norme de la boîte et dans l'idéal de code tutoriel à jour). Chaque développeur est néanmoins responsable du design de ses classes.
Nous mettons TOUTES nos variables de classes (côté model) en private. Nous utilisons un framework de binding (JGoodies Binding) et il FAUT toujours passer par les setters pour générer le comportement d'envoi des évènements de modification.
Côté Swing, celà dépend. Mais je sais par expérience, et surtout pour les débutants, qu'il est préférable d'avoir un maximum de restrictions (utiliser private et final autant que possible) sur les classes et éventuellement de "lever" certaines barrières par la suite que de tout permettre et se retrouver au final avec un code non maintenable.
C'est également plus facile de contrôler l'utilisation des classes maîtresses de l'application.
Selon moi et de façon plus générale, il serait préférable de ne JAMAIS ou presque avoir d'accès direct aux variables d'instance à partir d'autres classes mais d'avoir un mécanisme de getter/setter obligatoire car c'est comme ça qu'on a un contrôle maximal sur ce qui se passe et qu'on empêche une variable initialisée une fois pour toute d'être mise à null par un programmeur imprudent.
Je préfère prévoir l'utilisation qui sera faite de mes classes en ne permettant que ce que je souhaite permettre que de tout permettre et me voir assigner une liste de 100 bugs à cause d'un design permisif.Citation:
Envoyé par mathk
++
Citation:
Envoyé par millie
Si tu sous classe B c'est pour de bonne raison. Le minimum est de conaitre la super classe. Et si tes outils ne te permetent pas de lire facillement du code change les.
Redefinir check sans savoir quelle existe revien a faire en quelque sorte du sous-classage au lieu du sous-typage. Ce qui est du mauvais design.
Pour ma part je n'ai jamias eux ce genre de problemes.
Accéder a des variables par des mutateurs revient a avoir des variable public.Citation:
Envoyé par natha
En quelque sorte.
Je serais interesse par des exemples concret ou vous utilise des variables privateCitation:
Envoyé par natha
En aucune sorte !Citation:
Envoyé par mathk
Voici un exemple de classe métier nécessitant de n'avoir aucune variable statique car on souhaite toujours passer par les setters !
Et au niveau des getters différents de la variable public on peut imaginer ça :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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 public class Tutorial extends Model { // Names of the Bound Bean Properties ********************************************* public static final String PROPERTYNAME_NOM = "nom"; public static final String PROPERTYNAME_DESCRIPTION = "description"; public static final String PROPERTYNAME_GENTIL = "gentil"; public static final String PROPERTYNAME_DATE_JOUR = "dateJour"; public static final String PROPERTYNAME_NOMBRE1 = "nombre1"; public static final String PROPERTYNAME_NOMBRE2 = "nombre2"; public static final String PROPERTYNAME_CODE = "code"; // Instance Fields **************************************************************** private String m_nom; private String m_description; private boolean m_gentil; private Date m_dateJour; private int m_nombre1; private Integer m_nombre2; private TutorialCode m_code; /** * Default Constructor */ public Tutorial() { super(); } // Getters and setters ************************************************************ /** * @return Returns the nom. */ public String getNom() { return this.m_nom; } /** * @param nom The nom to set. */ public void setNom(String nom) { String oldValue = getNom(); this.m_nom = nom; firePropertyChange(PROPERTYNAME_NOM, oldValue, m_nom); } /** * @return Returns the description. */ public String getDescription() { return this.m_description; } /** * @param description The description to set. */ public void setDescription(String description) { String oldValue = getDescription(); this.m_description = description; firePropertyChange(PROPERTYNAME_DESCRIPTION, oldValue, m_description); } /** * @return Returns the gentil. */ public boolean isGentil() { return this.m_gentil; } /** * @param gentil The gentil to set. */ public void setGentil(boolean gentil) { boolean oldValue = isGentil(); this.m_gentil = gentil; firePropertyChange(PROPERTYNAME_GENTIL, oldValue, m_gentil); } /** * @return Returns the dateJour. */ public Date getDateJour() { return this.m_dateJour; } /** * @param dateJour The dateJour to set. */ public void setDateJour(Date dateJour) { Date oldValue = getDateJour(); this.m_dateJour = dateJour; firePropertyChange(PROPERTYNAME_DATE_JOUR, oldValue, m_dateJour); } /** * @return Returns the nombre1. */ public int getNombre1() { return this.m_nombre1; } /** * @param nombre1 The nombre1 to set. */ public void setNombre1(int nombre1) { int oldValue = getNombre1(); this.m_nombre1 = nombre1; firePropertyChange(PROPERTYNAME_NOMBRE1, oldValue, m_nombre1); } /** * @return Returns the nombre2. */ public Integer getNombre2() { return this.m_nombre2; } /** * @param nombre2 The nombre2 to set. */ public void setNombre2(Integer nombre2) { Integer oldValue = getNombre2(); this.m_nombre2 = nombre2; firePropertyChange(PROPERTYNAME_NOMBRE2, oldValue, m_nombre2); } /** * @return Returns the code. */ public TutorialCode getCode() { return this.m_code; } /** * @param code The code to set. */ public void setCode(TutorialCode code) { TutorialCode oldValue = getCode(); this.m_code = code; firePropertyChange(PROPERTYNAME_CODE, oldValue, m_code); } }
Ceci afin d'empêcher de pouvoir modifier la liste sans passer par le setList (ou d'autres méthodes à ajouter dans la classe qu'on pourrait appeler addItem ou removeItem).Code:
1
2
3
4
5
6
7
8
9
10 public static final String PROPERTYNAME_LIST = "list"; private List<String> m_list; public List<String> getList() { return m_list != null ? Collections.unmodifiableList(m_list) : null; } public void setList(List<String> list) { List<String> oldValue = getList(); this.m_list = list; firePropertyChange(PROPERTYNAME_LIST, oldValue, m_list); }
Voilà voilà, j'espère que c'est suffisant pour te faire comprendre l'utilité de private et le danger de tout mettre en protected ou public pour "se simplifier la vie" (pour moi c'est tout le contraire). Ceci n'est qu'un exemple parmi d'autres.
Qu'est ce que firePropertyChange est sense faire?Citation:
Envoyé par natha
Pourquoi tu donne la possibiliter au setter de retourner null. Pourquoi ne renverais tu pas une liste vide.Citation:
Envoyé par natha
Ca evite de faire des :
Code:
1
2 if (list != null) ...
Peut tu m'expliquer a quoi servent tes variables?Citation:
Envoyé par natha
Envoyer un évènement indiquant que la propriété untel a été modifiée de oldValue vers une new value. Renseigne toi sur le binding.Citation:
Qu'est ce que firePropertyChange est sense faire ?
C'était juste un exemple de code pour illustrer l'utilité du getter pour faire autre chose que ce que ferait une variable publique. Après null ou pas, c'est une question de contexte.Citation:
Pourquoi tu donne la possibiliter au setter de retourner null. Pourquoi ne renverais tu pas une liste vide.
C'est du code tuto donc ça ne sert pas à grand chose ici. M'enfin sur le concept c'est un objet métier (partie Model en MVC). Ces variables décrivent mon objet, c'est tout... m'enfin je vais pas te faire un cours de conception objet.Citation:
Peux tu m'expliquer a quoi servent tes variables ?
Sauf qu'avec null tu peux rien faire avec et tu auras surement des tests pour voir si ta variable est null ce qui est mocheCitation:
Envoyé par natha
Ok donc a priori il me faut un cour objet. Donc suposons que tu as developper cette super classe et que moi qui suis moin bon que toi en objet je veuille la reutilisé.Citation:
Envoyé par natha
Mais je n'aime pas l'implementation de ton getter pour ta List.
Je ne veux plus faire de tests car je sais que ma variable est jamais null. Et j'ai besoin de performances
Donc je fais une sous class. Manque de pos tu as declare ta variable private je peux donc pas accede a ta variable ...
En gros tu as une idée fixe et rien ne te fera changer d'avis...
null peut avoir du sens, par exemple que je n'ai pas récupéré ces données en BDD. Si c'est null c'est que je dois faire un select, si c'est liste vide c'est que j'ai déjà fait un select (mais ça reste un exemple).Citation:
Sauf qu'avec null tu peux rien faire avec et tu auras surement des tests pour voir si ta variable est null ce qui est moche
Et puis si tu ne veux pas que ça soit null tu as qu'à l'initialiser dans le constructeur de ta sous-classe... Et comme je l'ai dit ici ce n'est qu'un exemple de l'utilité du getter.
En fait toi tu veux pouvoir faire n'importe quoi avec une classe qui n'a pas été conçue pour pouvoir être utilisée n'importe comment.Citation:
Donc je fais une sous class. Manque de pos tu as declare ta variable private je peux donc pas accede a ta variable ...
Tu peux accéder à ma variable via les accesseurs. Je dirais même plus : tu DOIS utiliser les accesseurs. Et l'argument des performances est ridicule car si tu n'as aucun listener sur l'objet, passer par les getters/setters est quasiment autant rapide que passer directement sur la variable. Si tu as vraiment besoin de performances pures tu n'utiliseras clairement pas des classes modélisées comme ça et on pourrait faire une exception au "tout private" mais toi tu dis que tu veux du "tout public" ce qui est une abération.
Bonjour,
Pour rebondir sur l'aspect "null", je suis également contre les instanciations systématiques car "null" est porteur d'information (comment je sais interpréter la même chose avec un objet instancié à la new MonObjet() mais finalement pas vraiment initialisé ?).
Pour en revenir au thème initial, il manque quelque chose d'important dans les dernières interventions, et je pense que c'est ca qui nous intéresse dans le "Private vs Protected" : les attributs d'un objet qu'il n'expose pas à "tout le monde".
En effet, si vous définissez des mutateurs publics (des vrais, pas ceux qui font plus que ce qu'on attend d'eux d'un point de vue extérieur), c'est finalement un faux problème puisque n'importe quel objet pourra modifier l'état de l'attribut, y compris les classes filles.
Par contre, pour un attribut qui n'est pas exposé directement (qui est modifié indirectement par des méthodes de type "ajouter" ou des méthodes métier), servant uniquement à l'état interne de l'objet, on en revient à la question du design, de la classe finale car non dérivable, ou de celle qui peut être sous-classée.
Eric
Une courte intervention sans rapport direct avec le sujet initial. Les accesseurs servent egalement a cacher l'implementation de cette meme propriete. Cette propriete peut etre :
- un membre d'instance de la classes private ou protected. Generalement dans ce cas il faut gerer les evenement manuellement.
- une valeur stockee dans un objet repository (voir PropertyChangeSupport ainsi que les methodes putClientProperty() et getClientProperty() dans les JComponent).
- etre delegee a un sous-objet dans le cas d'une composition complexe. En cas de gestion d'evenement, l'objet courant ecoute les proprietes de l'objet delegue et forwarde l'evenement en remplacant la source par lui-meme.
- a partir de Java 7 il devrait etre possible de specifier qu'un membre est une propriete (via une annotation je crois) et beneficier ainsi automatiquement d'accesseurs. Par contre je ne sais pas ce qu'il en sera de la propagation des evenements.
Les composants Swing utilisent un mix des 3 premieres solutions :
- les proprietes heritees ou similaires a celles de l'AWT sont souvent des membres.
- les proprietes plus recentes utilisent putClientProperty() et getClientProperty().
- les composants les plus complexes forwardent les proprietes de sous-composants auxquels ils deleguent le boulot en creant un nouvel evenement dont il sont la source (par exemple une surcharge des proprietes du UIDelegate ou du modele).
Salut,
Moi je met tout en private. Même si la classe est étendue.
Si j'ai besoin, je met un getter (public ou protected).
Salut,
On pourrait peut-être aussi considérer le problème sous un autre angle que celui de l'héritage de classe. Je pense que le fait de déclarer ses variables d'instance comme private, en fournissant des getter/setter, te permet aussi à toi développeur de pouvoir modifier par la suite l'implémentation de ta classe sans affecter d'autre code l'utilisant.
Supposons que j'ai une classe comme celle-ci :
Et si par la suite, pour une raison ou une autre (contrainte sur une base de données existante par exemple...), j'ai besoin que ma date soit stockée non plus comme une variable de type Date mais juste comme une variable de type long, je n'aurais qu'à réaliser la modification suivante dans ma classe :Code:
1
2
3
4
5
6
7
8
9
10
11
12 import java.util.Date; public class A { private Date date; public Date getDate() { return this.date; } public void setDate(Date date) this.date = date; } }
L'implémentation interne de la classe a changé mais pas son interface, donc les autres classes ne seront pas affectées puisqu'elles n'utilisent que les méthodes publiques prévues pour ça. Alors que si j'avais donné un accès public à cette variable, à coup sûr une telle modification aurait des conséquence désastreuses pour tout code qui utiliserait directement cette variable sous la forme instanceA.dateCode:
1
2
3
4
5
6
7
8
9
10
11
12 import java.util.Date; public class A { private long date; public Date getDate() { return new Date(this.date); } public void setDate(Date date) this.date = date.getTime(); } }
Bon, évidemment l'exemple que j'ai pris est un peu simpliste, mais il n'est pas rare de tomber sur des cas réels qui demandent de prendre de telles décisions.
Conclusion : Utiliser private autant que possible pour s'assurer non seulement la protection de son code, mais aussi la possibilité de pouvoir modifier son fonctionnement interne sans affecter ses classes clientes.
Excellente remarque. :king:Citation:
Envoyé par manblaizo
Je n'ai jamais dit tous public.Citation:
Envoyé par natha
:roll: les gens sont soit tous soit rien il n'arrive jamais a se poser et réfléchir 5min
Moi je suis plus pour protected.
Citation:
Envoyé par manblaizo
Dans ton exemple tu n'as pas besoin de private. protected suffit
Mais si quelqu'un a la mauvaise idée d'hériter de la classe, d'utiliser directement le champ. Et si un jour l'implémentation de la classe change, il risque d'y avoir un problème, alors qu'en mettant private avec un accesseur (accesseur qui peut faire autre chose que simplement donner la valeur), il n'y aurait pas eu ce soucis.Citation:
Envoyé par mathk
Je ne te confierais jamais un design d'application... :| :nono:Citation:
Envoyé par mathk
En fait tu as posé la question pour essayer de valider ce que tu fais déjà et même si tout le monde te dit et te démontre que ce n'est pas la meilleure chose à faire, tu restes bloqué sur ton truc...
Un petit point à ne pas oublier, c'est que la visibilité de protected ce ne sont pas que les classes dérivées, mais également le package...
En ce qui me concerne, j'ai retenu 2 arguments pour le private que je partage à 100% :
- Le besoin de faire des choses dans les setters. Le cas du propertyChange est vraiment typique. A noter que c'est quelquechose qu'on peut avoir besoin de rajouter après ! Si tu n'as pas conçu avec des getters/setters, c'est vraiment chiant à changer !
- Le besoin de changer l'implémentation interne sans conséquence pour l'extérieur : c'est tout de même le principe de base de l'encapsulation !!
En contre, j'ai retenu un seul argument, que je ne partage pas du tout : le côté pénible des setters/getters...
En 2007, avec les IDEs qu'on a, vous n'allez pas m'expliquer que c'est plus pénible à taper.
Quant à la lisibilité, c'est vraiment une pure question d'habitude ...
Donc pour moi, effectivement c'est tout private sauf bonne raison pour que ce ne soit pas le cas.
Reste la question effectivement des attributs qu'on ne voudrait pas exposer (donc pas de getter/setters publics). Pour moi dans ce cas il faut clairement distinguer deux cas différents :
- On est en train de développer une appli, et si besoin est ultérieurement on pourra changer la visibilité d'un getter/setter ou rajouter un getter/setter
- On est en train de développer une API. Ce cas est beaucoup plus complexe effectivement ! Car il faut vraiment réfléchir et imaginer les besoins futurs en termes d'héritage et de redéfinition ... Mais cela concerne pas plus d'1% d'entre nous :P
Concernant les question de design, je vais souvent m'inspirer du côté des sources de Sun, par exemple les implémentations de ArrayList AbstractList etc.
(Au passage, on peut comparer ces classes avec Vector, de conception plus ancienne, qui justement comportait des attributs protected.)
On se rend compte qu'il y a finalement assez souvent d'accès package, mais le plus souvent du private, ce qui tend à me faire pencher vers cette solution comme la meilleure.
Mais pour moi cette question concerne surtout celle des API (donc 1% des cas comme on disait) mais aussi du framework interne ou même de classes utilitaire au sein d'un projet.
De plus je me permet de glisser que je vois beaucoup de setter public, ce qui revient à appliquer la règle pour appliquer la règle, moi j'aurais plus tendance à éviter au maximum les setters public pour péférer du protected, faire très attention aux getters sur des types Collection Map ou List (qui permettent une modification du contenu sans contrôle)
Pour finir, sur des Classes "projet" d'objets métiers ou autre, je me suis trop souvent retouvé bloqué par la classe d'un autre qui était trop verrouillée pour imposer ça à mes petits copains, donc j'utilise encore pas mal l'accès protected sur les attributs de ce type de classe. En me disant qu 'au sein d'un projet, il est très facile d'utiliser le refactor pour déplacer du code, remplacer les variables par des getters etc... s'il faut.
Pour avoir vu des normes trop restrictives, je n'ai pas d'avis trop définitif sur ces définitions, il y a des grandes règles à appliquer, mais c'est une bonne conception objet qui prime, et cela, aucune norme ne peut l'imposer.
(edit précisions.)
de toute façon j'utilise un langage qui ne laisse pas le choix de la visibilité. De plus en Java il y a 4 niveaux de visibilité. Les choses sont toujours complexe en java. En lisant le code source de certaine application l'on s'en rend compte tres vite : (Argouml, Azureus, BlueJ...)Citation:
Envoyé par natha
Un langage qui peux être intéressant du point de vu de la visibilité serai celle Ruby (Juste pour le private)
Mon intention aura été juste de partager mon expérience car des attributs private pose toujours des problèmes pour le future