Aller au contenu principal

L'encapsulation

getters et setters

Notions théoriques

L'encapsulation

L'encapsulation est le premier pilier de la POO. Elle consiste à :

  1. Cacher les données internes d'une classe (attributs private)
  2. Exposer uniquement les opérations autorisées (méthodes public)

C'est comme une capsule : on ne voit pas l'intérieur, on ne peut interagir qu'avec ce qui est prévu.

// Sans encapsulation : dangereux
public class Personnage {
public int pointsDeVie; // n'importe qui peut écrire hero.pointsDeVie = -9999
}

// Avec encapsulation : sécurisé
public class Personnage {
private int pointsDeVie; // protégé

public void soigner(int points) {
if (points > 0) { // validation
pointsDeVie += points;
}
}
}

Les getters

Un getter est une méthode public qui retourne la valeur d'un attribut private. La convention de nommage en Java est getAttribut() :

private String nom;
private int force;
private boolean vivant;

// Getters
public String getNom() { return nom; }
public int getForce() { return force; }
public boolean isVivant() { return vivant; } // boolean : "is" au lieu de "get"
info

Pour les attributs de type boolean, la convention est d'utiliser is plutôt que get : isVivant(), isActif(), isEmpty().

Les setters

Un setter est une méthode public qui modifie la valeur d'un attribut private. La convention est setAttribut(Type valeur) :

private String nom;
private int force;

// Setters avec validation
public void setNom(String nom) {
if (nom != null && !nom.isBlank()) {
this.nom = nom;
}
}

public void setForce(int force) {
if (force >= 0) {
this.force = force;
} else {
throw new IllegalArgumentException("La force ne peut pas être négative");
}
}

La validation dans les setters est l'un des grands avantages de l'encapsulation : on garantit que l'objet reste dans un état cohérent.

Générer avec IntelliJ

IntelliJ peut générer automatiquement les getters et setters :

  1. Placez le curseur dans la classe
  2. Appuyez sur Alt+Inser (Windows/Linux) ou Cmd+N (Mac)
  3. Choisissez Getter and Setter
  4. Sélectionnez les attributs pour lesquels générer

Quand ne pas faire de setter ?

Tous les attributs n'ont pas forcément besoin d'un setter. Si une valeur ne doit pas changer après la création de l'objet (par exemple, le nom d'un personnage), ne créez pas de setter. Exposez plutôt des méthodes métier qui décrivent l'action :

// Moins bien : trop générique
public void setPointsDeVie(int pv) { this.pointsDeVie = pv; }

// Mieux : méthodes métier expressives
public void soigner(int points) { this.pointsDeVie += points; }
public void recevoirDegats(int degats) { this.pointsDeVie -= degats; }

Exemple pratique

// Fichier : Personnage.java
public class Personnage {
private String nom;
private int force;
private int defense;
private int pointsDeVie;
private static final int PV_MAXIMUM = 200;

public Personnage(String nom, int force, int defense, int pointsDeVie) {
this.nom = nom;
setForce(force); // utilise le setter pour valider
setDefense(defense);
setPointsDeVie(pointsDeVie);
}

// --- Getters ---
public String getNom() { return nom; }
public int getForce() { return force; }
public int getDefense() { return defense; }
public int getPointsDeVie() { return pointsDeVie; }
public boolean isVivant() { return pointsDeVie > 0; }

// --- Setters avec validation ---
public void setNom(String nom) {
if (nom != null && !nom.isBlank()) {
this.nom = nom;
}
}

public void setForce(int force) {
if (force < 0) throw new IllegalArgumentException("La force doit être positive");
this.force = force;
}

public void setDefense(int defense) {
if (defense < 0) throw new IllegalArgumentException("La défense doit être positive");
this.defense = defense;
}

public void setPointsDeVie(int pointsDeVie) {
this.pointsDeVie = Math.max(0, Math.min(pointsDeVie, PV_MAXIMUM));
}

// --- Méthodes métier ---
public void soigner(int points) {
setPointsDeVie(pointsDeVie + points); // passe par le setter
}

public void recevoirDegats(int degats) {
int effectifs = Math.max(0, degats - defense);
setPointsDeVie(pointsDeVie - effectifs);
System.out.println(nom + " perd " + effectifs + " PV. Restants : " + pointsDeVie);
}

public void afficher() {
System.out.println(nom + " : Force=" + force + ", Def=" + defense + ", PV=" + pointsDeVie);
}
}

Test de mémorisation/compréhension


Quel est le nom conventionnel du getter pour l'attribut `force` en Java ?


Pour un attribut `boolean vivant`, quel est le nom conventionnel du getter ?


Quel est le principal avantage d'un setter par rapport à un accès direct à un attribut public ?


Dans un constructeur, peut-on appeler les setters pour initialiser les attributs ?


Un attribut `private final String nom` peut-il avoir un setter ?


TP pour réfléchir et résoudre des problèmes

Vous allez transformer la classe Personnage pour encapsuler correctement tous ses attributs avec des getters et des setters validants.

Étape 1 — Getters pour tous les attributs

Ajoutez des getters pour nom, force, defense et pointsDeVie.


Bonne pratique - Getters courts et sans logique

Les getters doivent être courts et ne contenir aucune logique métier. Leur rôle est uniquement de lire et retourner une valeur. Toute logique de transformation doit être dans une méthode métier distincte.

Étape 2 — Setter avec validation pour la force

Ajoutez un setter setForce(int force) qui rejette les valeurs négatives avec une exception.


Bonne pratique - Valider dans les setters

Toujours valider les données entrantes dans les setters. Lancez une IllegalArgumentException avec un message clair si la valeur est invalide. Cela évite que l'objet se retrouve dans un état incohérent (par exemple, une force négative n'a pas de sens dans un jeu RPG).

Étape 3 — Utiliser le setter dans le constructeur

Modifiez le constructeur pour qu'il appelle les setters au lieu d'assigner directement les attributs, afin de bénéficier de la validation dès la création.


Bonne pratique - Réutiliser les setters dans le constructeur

En appelant les setters depuis le constructeur (plutôt que d'assigner directement avec this.force = force), vous centralisez la logique de validation en un seul endroit. Si la règle de validation change, vous n'avez à modifier que le setter, pas le constructeur.

📌 Une solution