Bonjour,
Est-ce qu'une variable peut être protected et en même temps private. Si oui comment ça s'écrit?
Merci
Bonjour,
Est-ce qu'une variable peut être protected et en même temps private. Si oui comment ça s'écrit?
Merci
Est-ce qu'une variable peut être à la fois (1) uniquement visible par la classe où elle est définie, et (2) également visible par les classes qui en dérivent et les autres classes du package ?
Bah, euh, nan
=> que voulais-tu dire par "private" et "protected" ? que cherches-tu à faire ?
En fait le prof me donne un énoncé et il dit que toutes les variables sont protégées. Et il dit aussi que l'une d'entre elles doit être traitée par un modifieur (mutateur) et 2 autres par un accesseur.
Ca implique qu'il y a des variables qu'elles sont à la fois protected et private. Non?
à moins de me trompé une variable peut être Protected (voir même Public), mais avoir des getters/setters (mutateurs/accesseurs). Certes c'est contre productif, fait faisable. Donc je ne vois pas vraiment où est le problème.
Merci pour vos réponses. Donc si j'ai compris, je peux utiliser un mutateur et un modifieur avec un protected mais cela ne sert à rien. C'est ça? Et qu'est-ce qu'un package?
Qu'est-ce qu'un package... euh... mince je ne suis pas sure de savoir l'expliquer succintement
Pour s'y retrouver sur notre disque dur, nous rangeons nos fichiers dans des dossiers, avec une arborescence plus ou moins profonde (ex : documents>photos>2009>annivBidule).
Eh bien on fait pareil avec les classes Java, pour s'y retrouver on les range dans des packages (ex : java.util contient tout un tas de classes "utiles" pour de la programmation courante et contient plusieurs sous-packages plus spécifiques, comme java.util.zip ou java.util.regex).
Avant de définir une classe, tu dois indiquer à quel package elle appartient :
et ensuite tu peux utiliser cette classe en l'appelant par son nom complet (com.monprog.test.Test1) ou en effectuant un import préalable (import com.monprog.test.Test1; ou import com.monprog.test.*).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 package com.monprog.test; class Test1 {...}
Pour revenir à la question :
Définir des accesseurs sur une variable protected n'est pas idiot, ni inutile.
Si l'on veut qu'une variable définie dans une classe soit visible par les classes qui en héritent, alors il faut la déclarer protected (ou carrément public bien sûr). Si de plus on veut pouvoir accéder à cette variable depuis un autre package, il va falloir des accesseurs public.
Le problème c'est que Java ne permet pas de différencier visibilité par héritage et visibilité par package :
- private => visible par la classe uniquement
- protected => visible par la classe, par ses classes filles, et par les autres classes du même package
- public => visible par tout le monde
Du coup il peut sembler inutile de définir des accesseurs sur une variable protected (définie ainsi parce qu'on a besoin de l'utiliser par héritage) puisque de toutes façons toutes les autres classes du même package y auront librement accès (sauf que, comme je l'ai dit plus haut, depuis un autre package les accesseurs public seront nécessaires).
Pour comparer, en C# les deux notions sont séparées :
- private => visible par la classe uniquement
- protected => visible par la classe et par ses classes filles
- internal => visible par la classe et par les autres classes du même package
- public => visible par tout le monde
et on peut cumuler protected et internal si besoin...
Ok merci. Tin c'est chaud à comprendre quand même java. C'est pas très explicite. Genre quand j'entends "l'instanciation d'une classe" Mais bon maintenant je sais ce que c'est.
Salut
Je rajouterais une visibilité en Java:
- package only (quand il n'y a pas de modificateur de visibilité devant). La variable/classe est visible par les classes du même package seulement. Ce qui revient (presque) à internal en C#, car il me semble que internal n'est pas qu'une restriction sur le package, mais aussi sur la dll qui y accéde (ceci dit mes souvenirs en C# sont peut-être erronés)
A plus
Comme le dit George7 et contrairement à ce que dit Astartee :
En java, il y a bien 4 niveaux de visibilité. Le quatrième que tu n'as pas vu, c'est quand tu mets aucun mot clé, visibilité appelée "package-protected", visible uniquement par les classes du package.Le problème c'est que Java ne permet pas de différencier visibilité par héritage et visibilité par package
Comme le dit Astartee et contrairement à ce qu'on dit d'autres (inutile, pas conventionnel, contre productif),
- Ce n'est pas inutile car tu peux vouloir pour différentes raisons donner un accès direct à un attribut pour une sous classe et permettre en même temps son accès depuis l'extérieur via des getter/setter.
- La convention d'un getter et d'un setter, c'est uniquement pour les "java bean".
- L'utilisation d'un getter et ou d'un setter, c'est pour respecter le principe objet d'encapsulation des données. Ce qui te permet entre autre :
- de rendre une variable accessible uniquement en écriture (pas d'accesseur) ou uniquement en lecture (pas de mutateur)
- de cacher l'implémentation. C'est à dire que tu peux changer le code de ta classe sans impacter les clients de ta classe (au lieu d'être stocké, l'attribut peut être calculé par exemple).
- Avec l'utilisation d'outils moderne, la génération des get/set se fait en trois clics de souris.
Pour les packages, tu peux les voir de la manière suivante :
C'est ce qu'on appelle un espace de nommage.
Imagine juste que tu ne définis pas de package et que tu appelles ta classe List, comment la différencier de celle de java (java.util.List) ?
Le package te permet donc en quelque sorte de préfixer tes classes.
Le nom complet d'une classe (nom du package + nom de la classe) devrait en théorie être unique !
C'est pour cela :
- qu'on déconseille leur non utilisation ou les packages du style "librairie" ou "util"
- qu'on recommande (par convention) d'utiliser l'url de l'entreprise (http://ibm.com par ex.) en partant du plus général au plus spécifique - le tld, puis le domaine et les sous domaines - (com.ibm dans l'ex.)
Les packages te servent également à ranger ton code dès que tu as beaucoup de classes mais le but premier, c'est d'éviter les conflits de noms lorsqu'on veut utiliser ensemble des classes qui ont le même petit nom
Tiens donc. En fait je ne me suis jamais amusée à ne pas utiliser de mot-clé devant mes variables
Mais il n'y a donc toujours pas moyen d'avoir une variable visible par héritage uniquement ? (ça fait partie des trucs qui m'agacent en Java...)
En effet, il s'agit en fait d'une visibilité par "assembly" (traduction?)...
Ce que je trouve d'ailleurs encore plus pratique qu'une visibilité par package (=> possibilité d'utiliser plusieurs namespaces dans son projet tout en conservant l'avantage d'une visibilité interne au projet + impossibilité pour l'utilisateur de notre API de "contourner" la protection des variables/méthodes que l'on voulait cacher en se plaçant simplement dans le même namespace)
Là, tu as parfaitement raison et pour être honnête, je crois que ça m'a aussi agacé une fois avant que je réfléchisse à cette "limitation".
Tu écris une classe.
Si tu veux qu'une de ses méthodes soit visible pour les classes filles, tu mets protected (Les classes filles pouvant être en dedans ou en dehors du package)
Pourquoi interdire celles de ton package, ça n'a pas de sens ! C'est comme, si tu avais une porte qui te permette d'entrer chez toi, porte que tu réserves à tes amis mais que tu t'interdis d'utiliser !
Si tu veux qu'une de ses méthodes soit visible uniquement pour les classes de ton package, tu ne mets rien !
Le truc que tu ne peux pas faire, c'est limiter la visibilité aux classes filles dans ton package !
Mais là encore, quel est l'intérêt puisque c'est TON package !!! Dans TON package, si tu ne veux pas l'utiliser en dehors de classes filles, ne le fait pas!
Le seul que je vois, c'est un signe d'avertissement ! Comme si tu fermais une porte chez toi à clé mais que tu laisses la clé sur la porte
Ta remarque sur le contournement est également intéressante.
En effet, rien n'interdit d'utiliser un même nom de package pour contourner des limitations (Je crois juste qu'on peut indiquer à la JVM d'utiliser uniquement les classes de même package qui viendrait du même jar en le scellant mais cela n'empêche pas tout). En y réfléchissant un peu, pour que cela est un réel impact sur la librairie en question, il faut que tu disposes du code source ? Et si tu peux voir le source, tu peux également faire du copier/coller pour définir ton propre comportement.
Parce que les autres classes du package n'ont absolument aucune raison d'accéder à la vairable/méthode en question, et même qu'elles ne devraient pas me faire, et que je veux l'indiquer (et le forcer) proprement ?
Et le jour où quelqu'un d'autre vient mettre le nez dans le code (eh oui, en entreprise on tourne sur les projets, et le développeur initial peut avoir disparu dans la nature) ou alors le jour où je reprends mon projet après un temps suffisamment long pour avoir oublié pourquoi il ne fallait pas utiliser directement cette variable/méthode, ça casse...
OK, on peut mettre un gros commentaire "NE PAS UTILISER", mais c'est bof bof comme protection.
En disant "ça n'a pas de sens", je pensais uniquement aux classes dérivées de ton package. C'était oublier les autres où pour des raisons de sémantique, pouvoir interdire serait en effet plus propre. Je suis d'accord avec toi et c'est probablement pour cela que ça m'a agacé un jour !
Je suis là aussi d'accord pour le signe d'avertissement prévu par le langage car par le commentaire, c'est très critiquable.
Ce que je voulais te dire, c'est plutôt ça : OK, tu mets que ta variable est uniquement visible par les classes filles du package mais si celui qui passe après, ça le gêne, il aura tout pouvoir pour modifier.
Pour résumer, le niveau de visibilité que tu demandes
- a un réel intérêt d'un point de vue sémantique (c'est plus propre)
- n'a pas d'intérêt d'un point de vue sécurité vis à vis de l'extérieur (ce que je voulais dire)
Es tu d'accord avec cela ?
+1
Je trouve également que la visibilité du protected est bien trop large. Ce n'est pas parce que les classes filles doivent pouvoir y avoir accès que cela doit forcément être le cas pour les autres classes du même package !
Surtout qu'en l'absence d'équivalent à la visibilité assembly du C#, on se retrouve obligé de regrouper plusieurs classes dans un même package
(mais cela devrait normalement être possible avec les modules de Java 7)
Mais le pire c'est qu'il existait dans les toutes premières versions de Java une visibilité supplémentaire "private protected" qui limitait la visibilité uniquement aux classes filles ! Toutefois cette visibilité a été abandonné
a++
Oui, moi aussi (contrairement à ce que pouvais laisser croire mon premier message)
Je dis juste qu'au niveau "protection vis à vis de l'extérieur", ça n'a pas vraiment d'incidence non ?
L'autre jour, il me semble que c'est toi qui disait que si on a une classe p1.A et p1.B, pour "obliger" la JVM à prendre les classes du même package (p1) dans le même jar, il "suffisait" de sceller le jar où sont ces classes; que cela permet, si on a deux jar qui contiennent des classes éponymes de rester cohérent.
Tu n'as pas dit si cela s'applique à toutes les classes du package p1 ou aux classes référencées dans le package dans le jar ?
Je m'explique :
Supposons que p1.A utilise p1.B, j'ai compris que si la JVM va chercher p1.B dans le même jar scellé que celui où elle est allé cherché p1.A, cela interdit donc via un autre jar qu'une autre implémentation de p1.B vienne foutre le box.
Maintenant, via le mécanisme des interfaces et/ou des classes dérivées, supposons une classe p1.C qui implémente/étende p1.B mais que cette classe p1.C ne soit pas dans le jar scellé.
Est-ce que la JVM va aller le chercher dans les autres jar ? puisqu'elle n'est pas dans le jar scellé ou est-ce qu'elle va dire qu'elle ne la trouve pas ?
Je savais pas ... Et tu sais pourquoi ?
Oui on est d'accord là dessus
Lorsque tu scelles un package, toutes les classes seront obligatoirement chargé du meme jar : impossible donc de "remplacer" une classe ni d'ajouter une classe au package...
Pour simplifier le tout apparemment... Plus de détail ici : http://forums.sun.com/thread.jspa?threadID=5384410
Mais perso je ne pense pas que ce soit forcément le cas : la visibilité package du mot-clef protected surprend beaucoup de monde.
a++
Merci pour ces réponses.
En fait, on scelle le package et pas le jar, ce qui est plus clair.
Ça c'est sûr, si on reprend le projet et qu'on modifie le code on pourra de toutes façons accéder à ce qu'on veut Mais avant d'élargir une visibilité, le développeur va peut-être se demander pourquoi la méthode était privée, tandis que si rien ne restreint l'utilisation de la méthode il va moins se poser de questions...
C'est une question de rigueur et de "propreté". Ça c'est public, ça c'est privé, ça c'est privé - ah mais j'en ai besoin dans les classes dérivées quand même - ouais mais c'est pas censé être utilisé par les autres classes - bon bah tant pis, protected - et m*rde, maintenant à chaque autocomplétion dans les autres classes on va me proposer cette méthode que je ne suis pas censée utiliser...
Bref, on se débrouille avec ce qui existe, mais ça n'empêche pas de souhaiter l'existence de tout un tas de modifieurs d'accès (ça fait moche en français, non ?) permettant de définir de façon plus fine ce qu'on veut faire des membres de nos classes
Si les modifieurs d'accès de Java peuvent s'améliorer, tant mieux.
Par contre, dans ma boîte, on en est toujours à Java 1.4.2, alors je ne suis pas prête de pouvoir m'en servir au boulot
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