Classes et objets en Java
Prérequis
Maîtriser les types primitifs, les variables et la structure d'un programme Java. Avoir des notions de base sur la programmation procédurale.
Objectifs
Comprendre les concepts fondamentaux de la programmation orientée objet en Java : définir une classe, déclarer des attributs et des méthodes, créer des objets avec des constructeurs, et accéder aux membres via l'opérateur point.
Un peu d'histoire
La Programmation Orientée Objet (POO) est née dans les années 1960 avec le langage Simula. Elle a été popularisée par Smalltalk (1972) puis adoptée massivement par C++, Java et Python. Java a été conçu dès 1995 comme un langage entièrement orienté objet : tout code Java (hors types primitifs) est encapsulé dans des classes.
1. Les piliers de la POO en Java
| Concept | Description courte |
|---|---|
| Classe | Modèle (plan) décrivant les attributs et comportements d'un type d'objet |
| Objet | Instance concrète d'une classe, possédant un état et des comportements |
| Encapsulation | Regrouper données et méthodes, contrôler l'accès via des modificateurs |
| Héritage | Une classe peut hériter des attributs et méthodes d'une autre classe |
| Polymorphisme | Un même nom de méthode peut avoir des comportements différents selon le contexte |
| Abstraction | Exposer uniquement l'essentiel, cacher les détails d'implémentation |
2. La classe — modèle de l'objet
2.1 Syntaxe de déclaration
class NomDeLaClasse {
// ── Attributs (variables d'instance) ──
typeAttribut nomAttribut;
// ── Constructeur ──
NomDeLaClasse() {
// initialisation
}
// ── Méthodes ──
typeRetour nomMethode() {
// instructions
}
}
Exemple 1 — Classe Lampe
class Lampe {
// Attribut (variable d'instance)
private boolean isOn;
// Méthode — allumer la lampe
public void allumer() {
isOn = true;
}
// Méthode — éteindre la lampe
public void eteindre() {
isOn = false;
}
}
2.2 Les trois types de variables dans une classe
| Type de variable | Déclaration | Durée de vie | Accessibilité |
|---|---|---|---|
| Variable locale | Dans une méthode, un constructeur ou un bloc | Détruite à la fin de la méthode | Uniquement dans ce bloc |
| Variable d'instance | Dans la classe, hors de toute méthode | Tant que l'objet existe | Toutes les méthodes de la classe |
| Variable de classe | Dans la classe avec le mot-clé static |
Toute la durée de l'application | Partagée entre toutes les instances |
Exemple 2 — Les trois types de variables
class Compteur {
// Variable de classe (partagée par tous les objets)
static int nombreInstances = 0;
// Variable d'instance (propre à chaque objet)
private int valeur;
public void incrementer() {
// Variable locale (existe seulement dans cette méthode)
int pas = 1;
valeur += pas;
}
}
2.3 Les modificateurs d'accès
| Modificateur | Même classe | Même package | Sous-classe | Partout |
|---|---|---|---|---|
private |
✅ | ❌ | ❌ | ❌ |
| (aucun) | ✅ | ✅ | ❌ | ❌ |
protected |
✅ | ✅ | ✅ | ❌ |
public |
✅ | ✅ | ✅ | ✅ |
private et fournissez des méthodes public (getters / setters) pour y accéder. C'est le principe d'encapsulation — protéger l'état interne de l'objet.3. Les constructeurs
new. Il porte le même nom que la classe et n'a pas de type de retour. Son rôle est d'initialiser l'état de l'objet.- Le nom du constructeur doit être identique au nom de la classe.
- Un constructeur n'a pas de type de retour (même pas
void). - Si aucun constructeur n'est défini, Java génère automatiquement un constructeur par défaut (sans paramètre).
- Une classe peut avoir plusieurs constructeurs (surcharge).
Exemple 3 — Constructeurs et mot-clé this
class Lampe {
private boolean isOn;
// Constructeur par défaut — lampe éteinte
public Lampe() {
this.isOn = false;
System.out.println("Constructeur par défaut appelé");
}
// Constructeur d'initialisation — état défini par le paramètre
public Lampe(boolean etat) {
this.isOn = etat;
System.out.println("Constructeur d'initialisation appelé");
}
public static void main(String[] args) {
Lampe l1 = new Lampe(); // appelle le 1er constructeur
Lampe l2 = new Lampe(true); // appelle le 2nd constructeur
}
}
Constructeur par défaut appelé Constructeur d'initialisation appelé
this Dans un constructeur ou une méthode, this fait référence à l'objet courant. Il est indispensable quand un paramètre porte le même nom qu'un attribut : this.isOn désigne l'attribut, isOn seul désignerait le paramètre.4. Les objets en Java
new.4.1 Les trois étapes de création d'un objet
| Étape | Rôle | Exemple |
|---|---|---|
| 1 — Déclaration | Déclarer une variable référence du type de la classe | Lampe l1; |
| 2 — Instanciation | Allouer la mémoire avec new |
new Lampe() |
| 3 — Initialisation | Appeler le constructeur pour initialiser l'objet | l1 = new Lampe(); |
// Les trois étapes en une ligne
NomClasse nomObjet = new NomClasse(argumentsConstructeur);
4.2 Accès aux membres via l'opérateur point
. L'opérateur point permet d'accéder aux attributs et méthodes d'un objet : objet.attribut ou objet.methode().Exemple 4 — Création et utilisation d'objets
class Lampe {
private boolean isOn;
public Lampe() {
this.isOn = false;
}
public void allumer() {
isOn = true;
System.out.println("Lampe allumée");
}
public void eteindre() {
isOn = false;
System.out.println("Lampe éteinte");
}
public boolean getEtat() {
return isOn;
}
public static void main(String[] args) {
// Création de deux objets distincts
Lampe l1 = new Lampe();
Lampe l2 = new Lampe();
// Chaque objet a son propre état
l1.allumer();
System.out.println("l1 allumée ? " + l1.getEtat()); // true
System.out.println("l2 allumée ? " + l2.getEtat()); // false
l1.eteindre();
}
}
Lampe allumée l1 allumée ? true l2 allumée ? false Lampe éteinte
l1.isOn n'affecte pas l2.isOn. Les deux objets partagent la même définition (classe) mais ont des états distincts.5. Packages et instructions d'importation
import indique au compilateur où trouver les classes utilisées dans le fichier source, sans avoir à écrire leur nom complet à chaque fois.
// Importer une classe spécifique
import java.util.ArrayList;
// Importer toutes les classes d'un package
import java.io.*;
// Structure complète d'un fichier source
package ma.mp.cpge; // 1. déclaration du package
import java.util.ArrayList; // 2. imports
public class Etudiant { // 3. déclaration de la classe
// ...
}
- Un seul fichier source peut contenir une seule classe publique.
- Le nom de la classe publique doit correspondre exactement au nom du fichier (
.java). - L'instruction
packagedoit être la première ligne (avant tout import). - Les instructions
importviennent après le package et avant la déclaration de classe. - Un fichier peut contenir plusieurs classes non publiques.
Exemple 5 — Structure complète d'un fichier source
// 1. Package
package ma.mp.cpge.poo;
// 2. Imports
import java.util.ArrayList;
import java.util.List;
// 3. Classe publique (nom = nom du fichier : Ecole.java)
public class Ecole {
// Variable de classe
private static String nom = "MP";
// Variable d'instance
private List<String> etudiants;
// Constructeur
public Ecole() {
this.etudiants = new ArrayList<>();
}
// Méthode
public void ajouterEtudiant(String prenom) {
etudiants.add(prenom);
System.out.println(prenom + " ajouté(e) à " + nom);
}
public static void main(String[] args) {
Ecole e = new Ecole();
e.ajouterEtudiant("Mostafa");
e.ajouterEtudiant("Sara");
}
}
Mostafa ajouté(e) à MP Sara ajouté(e) à MP
6. Exercice
Modéliser un compte bancaire
On souhaite modéliser un compte bancaire simplifié. Un compte possède un titulaire (nom), un numéro de compte et un solde. Il peut recevoir des dépôts, des retraits et afficher son état.
Travail demandé
- Créer une classe
CompteBancaireavec les attributs :titulaire(String),numero(String),solde(double). - Écrire un constructeur d'initialisation prenant les trois valeurs en paramètre.
- Écrire une méthode
deposer(double montant)qui ajoute le montant au solde (vérifier que le montant est positif). - Écrire une méthode
retirer(double montant)qui soustrait le montant (vérifier que le solde est suffisant). - Écrire une méthode
afficherEtat()qui affiche toutes les informations du compte. - Dans le
main, créer deux comptes et simuler quelques opérations.
=== Compte de Mostafa === Numéro : 23123123123 Solde : 1500.0 MAD Dépôt de 500.0 MAD effectué. Retrait de 200.0 MAD effectué. Solde insuffisant pour retirer 2000.0 MAD. === Compte de Mostafa === Numéro : 23123123123 Solde : 1800.0 MAD
- Tous les attributs doivent être
private - Un retrait refusé affiche un message d'erreur sans modifier le solde
- Un dépôt de montant négatif ou nul est ignoré avec un message
public class CompteBancaire {
// ── Attributs privés ──────────────────────────────────
private String titulaire;
private String numero;
private double solde;
// ── Constructeur ──────────────────────────────────────
public CompteBancaire(String titulaire, String numero, double soldeInitial) {
this.titulaire = titulaire;
this.numero = numero;
this.solde = soldeInitial;
}
// ── Méthodes ──────────────────────────────────────────
public void deposer(double montant) {
if (montant <= 0) {
System.out.println("Montant invalide pour un dépôt.");
return;
}
solde += montant;
System.out.println("Dépôt de " + montant + " MAD effectué.");
}
public void retirer(double montant) {
if (montant > solde) {
System.out.println("Solde insuffisant pour retirer " + montant + " MAD.");
return;
}
solde -= montant;
System.out.println("Retrait de " + montant + " MAD effectué.");
}
public void afficherEtat() {
System.out.println("=== Compte de " + titulaire + " ===");
System.out.println("Numéro : " + numero);
System.out.println("Solde : " + solde + " MAD");
}
// ── Programme principal ───────────────────────────────
public static void main(String[] args) {
CompteBancaire c1 = new CompteBancaire("Mostafa", "FR7612345", 1500.0);
c1.afficherEtat();
c1.deposer(500.0);
c1.retirer(200.0);
c1.retirer(2000.0); // refusé — solde insuffisant
c1.afficherEtat();
}
}
=== Compte de Mostafa === Numéro : FR7612345 Solde : 1500.0 MAD Dépôt de 500.0 MAD effectué. Retrait de 200.0 MAD effectué. Solde insuffisant pour retirer 2000.0 MAD. === Compte de Mostafa === Numéro : FR7612345 Solde : 1800.0 MAD
- Encapsulation : les attributs sont
private— seules les méthodes de la classe peuvent les modifier directement. - Validation dans les méthodes :
deposeretretirervérifient les préconditions avant d'agir. - Constructeur d'initialisation : l'objet est dans un état cohérent dès sa création.
this: lève l'ambiguïté entre les paramètres et les attributs portant le même nom.
L'essentiel en bref
En Java, une classe est un modèle regroupant des attributs (état) et des méthodes (comportements). Un objet est une instance de classe créée avec new, possédant son propre état indépendant. Le constructeur — portant le nom de la classe — initialise l'objet à la création ; une classe peut en avoir plusieurs (surcharge). L'accès aux membres se fait via l'opérateur point (.). Les attributs sont généralement déclarés private (encapsulation) et les méthodes public. Les packages organisent les classes en namespaces, et les imports permettent d'utiliser des classes externes sans écrire leur chemin complet.