Encapsulation et portée¶
Vue d’ensemble rapide¶
| Modificateur | Accessible depuis… | Pour quoi ? |
|---|---|---|
public |
Partout (même autres packages) | API publiques, méthodes utilitaires, classes « visibles » |
protected |
Le même package + les sous-classes (même si elles sont dans un autre package) | Points d’extension pour l’héritage |
| (aucun) (package-private) | Uniquement le même package | Détails internes d’un module/package |
private |
Uniquement dans la classe (et ses classes internes) | Encapsulation stricte des données/implémentations |
Rappel important : Pour une classe de premier niveau, seuls
publicet (aucun) sont autorisés (pasprivate/protected).
Portée vs. Modificateurs d’accès (à ne pas confondre)¶
- Portée (scope) : « Où, dans le fichier/bloc, un nom est-il visible ? » (blocs
{}, méthodes, etc.). - Modificateurs d’accès : « Quelles autres classes/packages peuvent y accéder ? » (
private, package‑private,protected,public).
On peut avoir une portée large dans la classe (p. ex. un champ) mais un accès restreint (private).
Exemple compact dans un seul package¶
package demo;
public class Compte {
public String iban; // visible partout (à éviter pour un champ !)
protected double solde; // visible dans demo.* et dans les sous-classes
String banque; // package-private : visible dans demo.* seulement
private String pin; // visible seulement dans Compte
public Compte(String iban, String pin) {
this.iban = iban;
this.pin = pin;
}
public void depot(double montant) { // méthode publique (API)
solde += montant;
}
private boolean pinValide(String essai) { // aide interne
return pin.equals(essai);
}
}
class OutilInterne { // pas de modificateur => package-private
static void sync(Compte c) {
// c.banque (OK, même package)
// c.pin (ERREUR : private)
}
}
Points pédagogiques :
- Éviter les champs publics : préférer private + getters/setters (ou immutabilité).
- package-private (aucun mot-clé) est très utile pour les utilitaires internes d’un package.
Exemple inter-packages pour protected¶
p1/Base.java
package p1;
public class Base {
protected int x = 42;
int y = 7; // package-private (p1 seulement)
protected void hook() { /* extension point */ }
}
p2/Derive.java
package p2;
import p1.Base;
public class Derive extends Base {
void test() {
int a = this.x; // OK : protected + sous-classe (autre package)
hook(); // OK
// int b = this.y; // ERREUR : y est package-private dans p1
}
}
p2/HorsSousClasse.java
package p2;
import p1.Base;
public class HorsSousClasse {
void test() {
Base b = new Base();
// b.x; // ERREUR : protected n’est pas visible ici (pas sous-classe)
// b.y; // ERREUR : package-private (p1 seulement)
}
}
Points pédagogiques :
- protected est visible dans le package d’origine et dans les sous-classes, même situées dans un autre package.
- Hors sous-classe (et hors package), protected n’est pas accessible.
Bonnes pratiques (règles simples)¶
- Par défaut :
privatepour champs et méthodes d’implémentation.
→ Exposez une API publique minimale (constructeurs/méthodes nécessaires). package-privatepour partager des détails entre classes d’un même package sans les exposer à l’extérieur.protectedseulement si vous préparez une extension par héritage (hooks, template method, etc.).
→ Sinon, préférez la composition à l’héritage.publicpour la surface d’API stable : classes, constructeurs et méthodes que d’autres packages doivent utiliser.
Pièges fréquents¶
- Champs
public: fuyez (viol d’encapsulation, invariants fragilisés). - Confusion
protected: ce n’est pas « public pour tout le monde » — c’est package + sous-classes. - Classes de premier niveau
protected/private: interdit. - Tests unitaires : si les tests sont dans le même package, package‑private suffit souvent (inutile de tout mettre en
public).