Modificateurs d'accès en Java
Prérequis
Maîtriser la notion de classe, d'objet et de méthode en Java. Comprendre les concepts de package et d'héritage (notion de base). Connaître les mots-clés public, private vus dans les cours précédents.
Objectifs
Comprendre les quatre niveaux de visibilité en Java (private, package, protected, public). Maîtriser le principe d'encapsulation via les getters/setters. Savoir choisir le modificateur adapté à chaque membre d'une classe.
1. Qu'est-ce qu'un modificateur ?
- Modificateurs d'accès : contrôlent la visibilité depuis d'autres classes.
- Modificateurs sans accès : modifient d'autres propriétés (
static,final,abstract…).
Ce cours se concentre sur les modificateurs d'accès, qui sont au cœur du principe d'encapsulation.
2. Les quatre niveaux d'accès
| Modificateur | Même classe | Même package | Sous-classe | Partout |
|---|---|---|---|---|
private |
Oui | Non | Non | Non |
| (aucun — package) | Oui | Oui | Non | Non |
protected |
Oui | Oui | Oui | Non |
public |
Oui | Oui | Oui | Oui |
private, méthodes utilitaires internes private, API publique public.3. Accès par défaut — package-private
Exemple 1 — Membres sans modificateur
package ma.um6p.cpge;
public class CompteurPackage {
int valeur; // package-private — accessible dans le même package
String description; // package-private
void incrementer() { // package-private
valeur++;
}
}
package ma.um6p.cpge; // même package : accès autorisé
class UtilisateurCompteur {
public static void main(String[] args) {
CompteurPackage c = new CompteurPackage();
c.valeur = 10; // accessible (même package)
c.incrementer(); // accessible (même package)
System.out.println(c.valeur); // 11
}
}
package ma.um6p.autre; // package différent
import ma.um6p.cpge.CompteurPackage;
class Test {
public static void main(String[] args) {
CompteurPackage c = new CompteurPackage();
c.valeur = 5; // Erreur de compilation : valeur has package access
}
}
4. Modificateur private
private n'est accessible que depuis l'intérieur de la classe où il est défini. Il est invisible depuis toute autre classe, même dans le même package. private est le fondement de l'encapsulation.private (elle serait inutilisable). Seuls les membres (attributs, méthodes, constructeurs) et les classes internes peuvent être private.4.1 Encapsulation avec getters et setters
Les attributs private sont exposés de manière contrôlée via des méthodes publiques d'accès (getters) et de modification (setters).
// Getter — lire la valeur
public TypeAttribut getNomAttribut() {
return nomAttribut;
}
// Setter — modifier la valeur
public void setNomAttribut(TypeAttribut valeur) {
this.nomAttribut = valeur;
}
Exemple 2 — Classe Personne avec attributs privés
public class Personne {
// Attributs privés — invisibles de l'extérieur
private String nom;
private int age;
// Constructeur
public Personne(String nom, int age) {
this.nom = nom;
setAge(age); // on utilise le setter pour bénéficier de la validation
}
// Getter — lecture du nom
public String getNom() {
return nom;
}
// Setter — modification du nom
public void setNom(String nom) {
if (nom != null && !nom.isBlank()) {
this.nom = nom;
}
}
// Getter — lecture de l'âge
public int getAge() {
return age;
}
// Setter avec validation — modification de l'âge
public void setAge(int age) {
if (age >= 0 && age <= 150) {
this.age = age;
} else {
System.out.println("Âge invalide : " + age);
}
}
public static void main(String[] args) {
Personne p = new Personne("Mostafa", 30);
System.out.println(p.getNom() + " a " + p.getAge() + " ans");
p.setAge(-5); // refusé par la validation
p.setAge(31); // accepté
System.out.println("Nouvel âge : " + p.getAge());
// p.age = 25; // Erreur de compilation — private !
}
}
Mostafa a 30 ans Âge invalide : -5 Nouvel âge : 31
p.age = -5) ne permettrait aucun contrôle. C'est l'un des principaux bénéfices de l'encapsulation.5. Modificateur public
public est accessible depuis n'importe quelle classe, quel que soit le package. Si la classe elle-même se trouve dans un autre package, elle doit être importée, mais l'accès à ses membres public est alors autorisé.Exemple 3 — Membres publics
public class Calculatrice {
// Méthode publique — accessible partout
public double additionner(double a, double b) {
return a + b;
}
public double diviser(double a, double b) {
if (b == 0) {
afficherErreur("Division par zéro !"); // appel d'une méthode privée
return 0;
}
return a / b;
}
// Méthode privée — détail d'implémentation interne
private void afficherErreur(String msg) {
System.err.println("Erreur : " + msg);
}
}
// Depuis une autre classe ou package
Calculatrice calc = new Calculatrice();
System.out.println(calc.additionner(3, 4)); // 7.0 — public : accessible
// calc.afficherErreur("test"); // Erreur — private : inaccessible
main() doit obligatoirement être déclarée public pour que la JVM puisse l'appeler depuis l'extérieur de la classe lors du lancement du programme.
public static void main(String[] args) { ... }
6. Modificateur protected
protected est accessible :
- depuis toutes les classes du même package,
- depuis toutes les sous-classes (même dans un autre package via héritage).
Exemple 4 — protected entre packages via héritage
// Package p1
package p1;
public class Animal {
protected String nom;
// Méthode protected — accessible par les sous-classes
protected void seDeplacer() {
System.out.println(nom + " se déplace.");
}
// Méthode private — inaccessible même aux sous-classes
private void respirer() {
System.out.println("Respiration interne.");
}
}
// Package p2 — autre package
package p2;
import p1.Animal;
public class Chien extends Animal {
public Chien(String nom) {
this.nom = nom; // nom est protected → accessible dans la sous-classe
}
public void aboyer() {
System.out.println(nom + " aboie !");
seDeplacer(); // protected → accessible dans la sous-classe
// respirer(); // Erreur — private → inaccessible
}
public static void main(String[] args) {
Chien c = new Chien("Rex");
c.aboyer();
}
}
Rex aboie ! Rex se déplace.
6.1 Règles d'héritage et modificateurs d'accès
- Une méthode
publicredéfinie doit resterpublic. - Une méthode
protectedredéfinie peut devenirprotectedoupublic. - Une méthode
privaten'est pas héritée — elle n'est donc pas redéfinissable.
class Base {
public void methodePublique() { }
protected void methodeProtegee() { }
private void methodePrivee() { }
}
class Derivee extends Base {
public void methodePublique() { } // maintenu public
public void methodeProtegee() { } // élargi : protected → public (autorisé)
// protected void methodePublique() { } // Erreur : restreint de public à protected
}
7. Comparaison complète et guide de choix
| Situation | Modificateur recommandé | Raison |
|---|---|---|
| Attribut de classe | private |
Encapsulation — accès uniquement via getters/setters |
| Méthode de l'API publique | public |
Accessible aux utilisateurs de la classe |
| Méthode utilitaire interne | private |
Détail d'implémentation, non exposé |
| Méthode partagée avec sous-classes | protected |
Accessible en héritage, cachée ailleurs |
| Classe utilitaire dans un package | (aucun — package-private) | Visible dans le package, cachée à l'extérieur |
Constante partagée (static final) |
public static final |
Constante globale accessible partout |
8. Exercice
Concevoir une classe CompteBancaire encapsulée
Concevoir une hiérarchie de classes bancaires en appliquant les bons modificateurs d'accès à chaque membre.
Travail demandé
- Créer une classe
Compteavec :private double solde— solde du compteprivate String numeroCpte— numéro de compteprotected String titulaire— accessible aux sous-classes- Un constructeur
publicinitialisant les trois attributs - Un getter
public getSolde()et un getterpublic getNumeroCpte() - Une méthode
protected crediter(double montant)— accessible aux sous-classes - Une méthode
private validerMontant(double montant)— vérification interne
- Créer une sous-classe
CompteCourant extends Compteavec :- Un attribut
private double decouvertMax - Une méthode
public debiter(double montant)qui autorise le découvert jusqu'àdecouvertMax
- Un attribut
- Tester dans un
mainen créant unCompteCourantet en simulant des opérations.
Compte de Mostafa — N°FR001 — Solde : 1000.0 $ Crédit de 500.0 $. Nouveau solde : 1500.0 $ Débit de 1800.0 $. Nouveau solde : -300.0 $ Découvert maximal atteint — débit refusé. Solde final : -300.0 $
- Les attributs de
Comptedoivent êtreprivateouprotectedselon le besoin validerMontantdoit êtreprivatecrediterdoit êtreprotected- Aucun accès direct à
soldedepuisCompteCourant
public class Compte {
// private — inaccessible même aux sous-classes
private double solde;
private String numeroCpte;
// protected — accessible dans CompteCourant
protected String titulaire;
// Constructeur public
public Compte(String numeroCpte, String titulaire, double soldeInitial) {
this.numeroCpte = numeroCpte;
this.titulaire = titulaire;
this.solde = soldeInitial;
}
// Getters publics — seul accès autorisé à solde et numeroCpte
public double getSolde() { return solde; }
public String getNumeroCpte() { return numeroCpte; }
// private — méthode utilitaire interne, non exposée
private boolean validerMontant(double montant) {
return montant > 0;
}
// protected — accessible aux sous-classes, cachée à l'extérieur
protected void crediter(double montant) {
if (validerMontant(montant)) {
solde += montant;
System.out.printf("Crédit de %.1f $. Nouveau solde : %.1f $%n",
montant, solde);
} else {
System.out.println("Montant invalide pour un crédit.");
}
}
// protected — permet aux sous-classes de modifier le solde avec validation
protected void setSolde(double solde) {
this.solde = solde;
}
// public — affichage des informations du compte
public void afficher() {
System.out.printf("Compte de %s — N°%s — Solde : %.1f $%n",
titulaire, numeroCpte, solde);
}
}
public class CompteCourant extends Compte {
// private — spécifique à CompteCourant
private double decouvertMax;
public CompteCourant(String numeroCpte, String titulaire,
double soldeInitial, double decouvertMax) {
super(numeroCpte, titulaire, soldeInitial);
this.decouvertMax = decouvertMax;
}
// public — opération de débit spécifique au compte courant
public void debiter(double montant) {
if (getSolde() - montant >= -decouvertMax) {
setSolde(getSolde() - montant); // via setter protected
System.out.printf("Débit de %.1f $. Nouveau solde : %.1f $%n",
montant, getSolde());
} else {
System.out.println("Découvert maximal atteint — débit refusé.");
}
}
public static void main(String[] args) {
CompteCourant cc = new CompteCourant("FR001", "Mostafa", 1000.0, 500.0);
cc.afficher();
cc.crediter(500.0); // protected — accessible dans la sous-classe
cc.debiter(1800.0); // 1500 - 1800 = -300 > -500 : autorisé
cc.debiter(300.0); // -300 - 300 = -600 < -500 : refusé
System.out.printf("Solde final : %.1f $%n", cc.getSolde());
}
}
Compte de Mostafa — N°FR001 — Solde : 1000.0 $ Crédit de 500.0 $. Nouveau solde : 1500.0 $ Débit de 1800.0 $. Nouveau solde : -300.0 $ Découvert maximal atteint — débit refusé. Solde final : -300.0 $
private soldeetprivate numeroCpte: protégés même des sous-classes — accès uniquement via getters/setters.protected titulaireetprotected crediter(): partagés avecCompteCourantsans exposer à l'extérieur.private validerMontant(): détail d'implémentation purement interne àCompte.public debiter()etpublic afficher(): API publique accessible par tous les utilisateurs.CompteCourantne peut pas écriresolde = ...directement — elle passe parsetSolde()qui estprotected.
L'essentiel en bref
Java propose quatre niveaux de visibilité. private est le plus restrictif : accessible uniquement dans la classe elle-même — c'est le fondement de l'encapsulation. L'accès package-private (aucun mot-clé) limite la visibilité au package courant. protected étend cet accès aux sous-classes, même dans d'autres packages, ce qui est utile pour l'héritage. public est le plus permissif et rend le membre accessible partout. En pratique : déclarez les attributs private, exposez-les via des getters/setters public avec validation, et utilisez protected pour partager des comportements avec les sous-classes. Lors de la redéfinition d'une méthode, la visibilité ne peut jamais être restreinte.
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.