Programmation orientée objet
TypeScript 101, Télécom Paris
Trois questions sur la séance 2, tirées des QCM du cours.
Que fait saluer ?
D. saluer("Alice") n’affiche rien : elle fabrique une fonction (une fermeture).
Que vaut a.prix à la fin ?
1020undefineda est constB. b = a ne copie rien : a et b désignent le même objet.
Que vaut [3, 1, 4, 1, 5].reduce((acc, x) => acc + x, 10) ?
142410B. L’accumulateur part de 10, puis 10 + 3 + 1 + 4 + 1 + 5 = 24.
class : champs, constructeur, méthodes, thisprivate, get et setimplements, réutiliser avec extendsabstractDeux chapitres : 3.1 Classes et encapsulation, 3.2 Contrats, héritage et polymorphisme.
En séance 2, un objet ne portait que des données, et le code vivait à part :
Rien n’empêche d’écrire compte.solde = -500 n’importe où.
Une classe réunit les données et le code qui a le droit de les modifier. C’est ce qui permet de faire respecter des règles.
new réserve un objet vide et appelle le constructeurconstructor initialise les champsthis désigne l’instance sur laquelle la méthode s’exécuteOublier this est l’erreur numéro un
Dans une méthode, nom tout seul n’est pas le champ de l’objet. Le compilateur répond : Cannot find name 'nom'. Did you mean the instance member 'this.nom'?
Écrivez toujours this.nom.
Un modificateur devant un paramètre déclare et initialise le champ :
Strictement équivalent à la version longue.
Utilisez ce raccourci quand vous l’avez compris. La version longue reste parfaitement correcte.
public, private, protectedDécider ce qui est visible de l’extérieur. Par défaut, tout est public.
| Modificateur | Dans la classe | Classes filles | Extérieur |
|---|---|---|---|
public (défaut) |
oui | oui | oui |
protected |
oui | oui | non |
private |
oui | non | non |
Un invariant reste vrai pendant toute la vie de l’objet. Pour le vérifier, il suffit de relire les méthodes de la classe, pas tout le programme.
get et setIls s’utilisent comme des propriétés, mais exécutent du code.
class Temperature {
private celsius: number = 0;
get fahrenheit(): number { return this.celsius * 9 / 5 + 32; }
set fahrenheit(v: number) { this.celsius = (v - 32) * 5 / 9; }
}
const t = new Temperature();
t.fahrenheit = 100; // appelle le setter
console.log(t.fahrenheit); // 100 : appelle le getterget sans set : propriété calculée, en lecture seuleset : l’endroit naturel pour validerprivate n’est pas une protectionUne vérification du compilateur, rien de plus
Après transpilation, le champ existe comme n’importe quel autre et reste accessible depuis du JavaScript.
Ce que l’on cherche, c’est empêcher les erreurs de conception, pas déjouer un attaquant.
La notation JavaScript #solde protège aussi à l’exécution. Vous la croiserez dans du code récent.
staticIls appartiennent à la classe, pas aux instances : un seul exemplaire, partagé.
Trois new Numero() plus tard : Numero.numeroStatique vaut 3, chaque numero vaut 1.
Usage typique : une constante de classe, static readonly TAUX_TVA = 0.2.
| Situation | Choix |
|---|---|
| Des données qui circulent (catalogue, réponse d’API) | objet littéral + interface |
| Des données avec des règles à faire respecter | classe + private |
| Plusieurs variantes d’un comportement | classes + interface commune |
| Un calcul sans état | simple fonction |
Le critère décisif est la règle : sans invariant à défendre, un objet littéral suffit. Et le JSON reçu du réseau n’est jamais une instance.
src/scripts/app.ts
Le module choisit quelles classes sont visibles, private choisit quels membres.
implementsUne interface décrit ce qu’une classe doit savoir faire. Aucun code : un cahier des charges.
Ce tableau ne sait rien des classes concrètes. Il sait seulement que chaque élément répond à getVoltage(). On ajoutera demain un Refrigerateur sans toucher une ligne de ce code.
extends et superL’héritage exprime une relation « est un ».
class Person {
constructor(public name: string, public age: number) {}
logPerson(): void { console.log(`Name: ${this.name}, Age: ${this.age}`); }
}
class User extends Person {
occupation: string;
constructor(name: string, age: number, occupation: string) {
super(name, age); // constructeur de Person
this.occupation = occupation; // toujours APRÈS super()
}
}new User("Max", 30, "Dev").logPerson() fonctionne : la méthode est héritée.
supersuper(...) doit être appelé avant tout accès à this.
La raison est logique : tant que le constructeur de la mère n’a pas tourné, l’objet n’est pas initialisé.
super.logPerson() appelle la version de la mère« Plusieurs formes » : on manipule des objets de classes différentes à travers un type commun, et chacun exécute sa propre version d’une méthode.
Le type de la variable décide de ce qu’on a le droit d’appeler ; l’objet réel décide de quelle version s’exécute.
Aucun if, aucun switch sur le type.
Ajouter un cas se fait en ajoutant une classe, jamais en modifiant le code qui parcourt le tableau.
Quand on a réellement besoin du type concret, instanceof le donne :
Entre l’interface et la classe : du code partagé et des méthodes que les filles devront écrire. On ne peut pas l’instancier.
| Besoin | Outil |
|---|---|
| Un contrat, sans aucun code | interface |
| Du code partagé entre classes proches | abstract class |
| Créer des objets | class |
Une classe n’hérite que d’une seule classe, mais implémente autant d’interfaces qu’elle veut.
Bonne pratique : typez les tableaux et les paramètres par l’interface, pas par la classe abstraite.
Un vecteur n’est pas un point : il en contient deux.
Posez-vous la question à voix haute : « est-ce que X est un Y ? ». Si la phrase sonne faux, composez.
asas ne convertit rien et ne vérifie rien : il fait taire le compilateur.
instanceof et typeof vérifient réellement :
| Chapitre | La POO dedans |
|---|---|
| 5.1 JSON | une instance transformée en JSON perd ses méthodes |
| 5.2 Generics | une classe générique |
| 5.3 Exceptions | extends Error, instanceof |
| 7.2 Formulaires | une méthode comme écouteur, .bind(this) |
| 7.3 Web components | extends HTMLElement |
Chacun de ces chapitres contient un encadré « Rappel POO » qui renvoie ici.
Parcours essentiel, dans l’ordre
Ensuite
get, set et une constante de classe (entraînement)L’évaluation 1 porte sur les séances 1 à 3. Sa page, sur le site, donne la grille des compétences attendues.