Ch. 0 bis — Rappels de POO et tests
Objets, classes, encapsulation, héritage, interfaces, classes abstraites, transtypage et tests JUnit 5 — les prérequis du S2 remis au propre.
Ce qu'on est censé déjà savoir
Prérequis du S2
- Développement orienté objet : classes, objets, visibilité, encapsulation, interfaces, héritage, classes abstraites, UML
- Qualité de développement : outils (VSCode → IntelliJ, Git), tests, documentation, exceptions
Les langages à objets en 4 caractéristiques
- Toute chose est un objet (à part les types primitifs en Java) ;
- Un programme = des objets qui se disent quoi faire (envoi de messages) ;
- Chaque objet a un type précis (sa classe) ;
- Tous les objets d'un type reçoivent les mêmes messages → c'est la base du polymorphisme.
L'objet : identité, état, comportement
| Propriété | C'est quoi | Comment on la manipule |
|---|---|---|
| Identité | Ce qui le distingue de tout autre objet | == (et pas equals()) ; deux copies d'un livre restent 2 objets |
| État | Ses données | Stocké dans les attributs |
| Comportement | Ce qu'il sait faire | Défini par les méthodes |
La classe
Une classe définit ce qui est commun à tous ses objets :
- la nature et le nombre des attributs, le comportement (méthodes) ;
- comment les objets sont initialisés (constructeur) — en Java, pas de destructeur ;
- la création d'instances via
new.
Encapsulation
Mettre un objet d'une autre classe en attribut pour réutiliser tout ou partie de ses méthodes (méthodes déléguées). L'objet délégué n'est généralement pas visible depuis l'extérieur de la classe.
Héritage
Une hiérarchie de similarité : deux Employé ont plus en commun que deux Humain — la
description se spécialise en descendant. C'est le même principe que la taxonomie du vivant,
et en Java, Object en est la racine.
Object
└── Humain
└── Employé
├── Étudiant
└── EnseignantUne sous-classe :
- hérite des attributs et méthodes de sa super-classe ;
- peut ajouter des caractéristiques ;
- peut redéfinir des méthodes pour étendre le comportement.
Règle d'or de la redéfinition
Une redéfinition devrait a priori toujours faire un appel à super pour ne pas perdre le
comportement hérité.
Substituabilité
Une sous-classe peut toujours être utilisée à la place de sa super-classe : toutes les méthodes de la classe sont appelables sur les objets des sous-classes. C'est ce qui rend le polymorphisme possible.
Interfaces
Un contrat sur les méthodes : la signature des méthodes que les classes devront implémenter.
- Méthodes systématiquement
public, pas d'attributs ; - Contournement de l'héritage simple : une classe peut implémenter plusieurs interfaces (ce n'est pas de l'héritage multiple — les méthodes ne sont pas héritées de l'interface — mais ça permet un « polymorphisme multiple ») ;
- Une interface peut dériver d'une autre interface ;
- Lien avec la notion d'API : ce qui peut être utilisé.
interface Collection<E> {
boolean add(E e);
boolean contains(E e);
int size();
}
interface List<E> extends Collection<E> { E get(int idx); }
class ArrayList<E> implements List<E> { /* ... */ }Classes abstraites : l'entre-deux
Une classe abstraite définit une partie de son comportement et déclare des méthodes abstraites que les sous-classes devront implémenter.
- Outil de factorisation du code ;
- Pas de
newdirectement (mais constructeur possible, enprotected) ; - Une sous-classe concrète doit implémenter toutes les méthodes abstraites.
abstract class Vehicule {
protected int prix;
protected double vitesseMax;
protected int nbKm;
public abstract int getCoutConso(); // à définir par chaque fille
}
class Voiture extends Vehicule {
private double coutConsoAuKm;
@Override public int getCoutConso() { /* calcul voiture */ return 0; }
}
class Velo extends Vehicule {
@Override public int getCoutConso() { return 0; } // quasi nul à la pompe
}Transtypage (cast)
Le type déclaré d'une variable ne correspond pas toujours à son type réel — c'est une
conséquence directe de la substituabilité. Exemple JavaFX : une List<Node> peut contenir des
Button ou des Label.
Upcasting (vers le haut)
List<Node> lst;
lst.add(new Label("test")); // Label traité comme un Node : automatique, sans risqueDowncasting (vers le bas)
List<Node> lst;
if (lst.get(1) instanceof Label) {
Label label = (Label) lst.get(1);
label.setText("bla");
}- À faire seulement si on est sûr du type réel ;
- Nécessaire pour appeler une méthode qui n'existe que dans la sous-classe ;
- Le cast reste dans une même hiérarchie d'héritage : ce n'est pas un mécanisme de
conversion de données (
int i = (int) "123";est invalide).
instanceof : mauvaise pratique
L'idée du polymorphisme, c'est précisément de ne pas avoir à connaître le type réel de
l'objet. Si vous multipliez les instanceof, repensez votre conception.
Tests : JUnit 5
Librairie de test Java (version 5), l'équivalent des XUnit dans les autres langages.
« Never in the field of software development was so much owed by so many to so few lines of code. » — Martin Fowler
Les 4 phases d'un test
Set-up (optionnel) — créer le contexte du test : l'objet à tester, les données nécessaires
Exercise — exécuter la méthode à tester avec des données prédéfinies
Verify — vérifier le résultat par rapport à une valeur attendue
Tear-down (optionnel) — libérer les ressources utilisées
import org.junit.jupiter.api.*;
class MaClasseTest {
@BeforeEach
public void setup() { /* Set-up */ }
@Test
public void testXY() { /* Exercise + Verify */ }
@AfterEach
public void teardown() { /* Tear-down */ }
}ch0bis-rappels.pdf
R3 04-cours-0bis-Rappels.pdf · 22 diapositives
Chargement du document…
Dernière mise à jour le
Ch. 0 — Introduction
Pourquoi « ça marche » ne suffit plus : complexité, durée de vie, bugs célèbres et objectifs du cours R3.04.
Ch. 1 — Patrons de conception
Ce qu'est un patron, les trois familles, et les six patrons de base : Fabrique simple, Décorateur, Composite, Singleton, Stratégie et ObjetNull — avec leurs exemples Java.