Review cours Terminale NSI — POO, SQL, Sécurité, Soc, Calculabilité, Réseau
This commit is contained in:
@@ -248,6 +248,88 @@ Ces méthodes sont appelées des accesseurs et modificateurs. Elles sont optionn
|
||||
|
||||
-----------
|
||||
|
||||
## L'héritage
|
||||
|
||||
Jusqu'ici, nous avons créé des classes indépendantes les unes des autres. Mais en POO, il est possible de créer une classe à partir d'une autre classe existante : c'est le principe de l'**héritage**.
|
||||
|
||||
L'idée est simple : une classe **enfant** hérite de tous les attributs et méthodes d'une classe **parent**, et peut en ajouter de nouveaux ou en modifier certains.
|
||||
|
||||
> L'héritage modélise une relation **"est-un"** : un `EtudiantBoursier` **est un** `Etudiant`. À ne pas confondre avec la composition vue dans le TP Pokémon, qui modélise une relation **"a-un"** : un `Dresseur` **a des** `Pokemon`.
|
||||
|
||||
### Syntaxe de base
|
||||
|
||||
Supposons que l'on veuille créer un `EtudiantBoursier` qui est un `Etudiant` avec une bourse mensuelle en plus.
|
||||
|
||||
```python
|
||||
class EtudiantBoursier(Etudiant):
|
||||
def __init__(self, nom_etu, prenom_etu, spe1_etu, age_etu, bourse_mensuelle):
|
||||
super().__init__(nom_etu, prenom_etu, spe1_etu, age_etu)
|
||||
self.bourse = bourse_mensuelle
|
||||
```
|
||||
|
||||
Plusieurs choses à noter :
|
||||
|
||||
- `class EtudiantBoursier(Etudiant)` : on indique entre parenthèses la classe parent dont on hérite.
|
||||
- `super().__init__(...)` : on appelle le constructeur de la classe parent pour initialiser les attributs déjà définis. Cela évite de tout réécrire.
|
||||
- On ajoute ensuite les attributs propres à l'enfant (`self.bourse`).
|
||||
|
||||
```python
|
||||
>>> eb = EtudiantBoursier('Martin', 'Léa', 'NSI', 17, 250)
|
||||
>>> eb.nom
|
||||
'Martin'
|
||||
>>> eb.bourse
|
||||
250
|
||||
>>> eb.peut_avoir_son_permis
|
||||
False
|
||||
```
|
||||
|
||||
L'objet `eb` a accès à tous les attributs de `Etudiant` **et** à `bourse`.
|
||||
|
||||
### Surcharge de méthode
|
||||
|
||||
Un `EtudiantBoursier` peut avoir besoin d'une méthode `__repr__` différente de celle de `Etudiant`. On peut alors **surcharger** (redéfinir) la méthode dans la classe enfant :
|
||||
|
||||
```python
|
||||
class EtudiantBoursier(Etudiant):
|
||||
def __init__(self, nom_etu, prenom_etu, spe1_etu, age_etu, bourse_mensuelle):
|
||||
super().__init__(nom_etu, prenom_etu, spe1_etu, age_etu)
|
||||
self.bourse = bourse_mensuelle
|
||||
|
||||
def __repr__(self):
|
||||
return super().__repr__() + f' (boursier : {self.bourse}€/mois)'
|
||||
```
|
||||
|
||||
```python
|
||||
>>> eb = EtudiantBoursier('Martin', 'Léa', 'NSI', 17, 250)
|
||||
>>> eb
|
||||
Martin Léa (boursier : 250€/mois)
|
||||
```
|
||||
|
||||
Ici `super().__repr__()` appelle la version de la classe parent pour ne pas dupliquer le code.
|
||||
|
||||
### isinstance()
|
||||
|
||||
La fonction native `isinstance()` permet de vérifier si un objet est une instance d'une classe donnée — y compris via l'héritage :
|
||||
|
||||
```python
|
||||
>>> eb = EtudiantBoursier('Martin', 'Léa', 'NSI', 17, 250)
|
||||
>>> isinstance(eb, EtudiantBoursier)
|
||||
True
|
||||
>>> isinstance(eb, Etudiant)
|
||||
True
|
||||
```
|
||||
|
||||
`eb` est à la fois un `EtudiantBoursier` ET un `Etudiant`. C'est la conséquence directe de l'héritage.
|
||||
|
||||
### Exercices
|
||||
|
||||
1. Créez une classe `EtudiantInternational` qui hérite de `Etudiant` et possède un attribut supplémentaire `pays_origine`.
|
||||
2. Surchargez `__repr__` pour afficher le pays entre parenthèses.
|
||||
3. Créez une fonction `liste_internationaux(etudiants)` qui prend une liste d'`Etudiant` et renvoie uniquement les `EtudiantInternational`. Utilisez `isinstance()`.
|
||||
4. Que se passe-t-il si on appelle `anniversaire()` sur un `EtudiantBoursier` ? Pourquoi ?
|
||||
|
||||
-----------
|
||||
|
||||
Auteurs : Florian Mathieu, Enzo Frémeaux, Thimothée Decooster
|
||||
|
||||
Licence CC BY NC
|
||||
|
||||
Reference in New Issue
Block a user