POO : TP Pokémon en notebook seul, corrigé sans héritage
This commit is contained in:
@@ -642,108 +642,6 @@ C'est une **composition** d'objets : un `Pokemon` possède une liste d'objets `C
|
||||
|
||||
---
|
||||
|
||||
## Partie 5 : Héritage (hors programme)
|
||||
|
||||
### Exercice 8 : Sous-classes par type
|
||||
|
||||
```python
|
||||
class PokemonFeu(Pokemon):
|
||||
def __init__(self, nom, niveau=1, pv_max=100, attaque=10):
|
||||
super().__init__(nom, "Feu", niveau, pv_max, attaque)
|
||||
|
||||
def attaquer(self, cible):
|
||||
"""
|
||||
Attaque avec ×2 dégâts si la cible est de type Plante.
|
||||
"""
|
||||
degats = self.attaque
|
||||
if cible.type_pokemon == "Plante":
|
||||
degats = degats * 2
|
||||
print("C'est super efficace !")
|
||||
print(f"{self.nom} attaque {cible.nom} et inflige {degats} dégâts !")
|
||||
cible.subir_degats(degats)
|
||||
|
||||
|
||||
class PokemonEau(Pokemon):
|
||||
def __init__(self, nom, niveau=1, pv_max=100, attaque=10):
|
||||
super().__init__(nom, "Eau", niveau, pv_max, attaque)
|
||||
|
||||
def attaquer(self, cible):
|
||||
"""
|
||||
Attaque avec ×2 dégâts si la cible est de type Feu.
|
||||
"""
|
||||
degats = self.attaque
|
||||
if cible.type_pokemon == "Feu":
|
||||
degats = degats * 2
|
||||
print("C'est super efficace !")
|
||||
print(f"{self.nom} attaque {cible.nom} et inflige {degats} dégâts !")
|
||||
cible.subir_degats(degats)
|
||||
|
||||
|
||||
class PokemonPlante(Pokemon):
|
||||
def __init__(self, nom, niveau=1, pv_max=100, attaque=10):
|
||||
super().__init__(nom, "Plante", niveau, pv_max, attaque)
|
||||
|
||||
def attaquer(self, cible):
|
||||
"""
|
||||
Attaque avec ×2 dégâts si la cible est de type Eau.
|
||||
"""
|
||||
degats = self.attaque
|
||||
if cible.type_pokemon == "Eau":
|
||||
degats = degats * 2
|
||||
print("C'est super efficace !")
|
||||
print(f"{self.nom} attaque {cible.nom} et inflige {degats} dégâts !")
|
||||
cible.subir_degats(degats)
|
||||
```
|
||||
|
||||
**Explications :**
|
||||
|
||||
- `super().__init__(...)` appelle le constructeur de `Pokemon` : les sous-classes n'ont pas à réécrire l'initialisation des attributs, elles fixent seulement le type.
|
||||
- Chaque sous-classe **redéfinit** `attaquer`. Quand on écrit `salameche.attaquer(...)`, Python cherche d'abord la méthode dans `PokemonFeu`, et ne remonte à `Pokemon` que s'il ne la trouve pas.
|
||||
- Les trois méthodes `attaquer` se ressemblent beaucoup : c'est justement la question de l'exercice 10.
|
||||
|
||||
---
|
||||
|
||||
### Exercice 9 : isinstance() en pratique
|
||||
|
||||
```python
|
||||
>>> salameche = PokemonFeu("Salamèche", niveau=15, pv_max=70, attaque=12)
|
||||
>>> isinstance(salameche, PokemonFeu)
|
||||
True
|
||||
>>> isinstance(salameche, Pokemon)
|
||||
True
|
||||
```
|
||||
|
||||
`salameche` est une instance des deux classes, car `PokemonFeu` **hérite** de `Pokemon` : un Pokémon Feu **est un** Pokémon. Il possède tous ses attributs et toutes ses méthodes (`est_ko`, `soigner`...). C'est pour cela qu'on peut le placer dans l'équipe d'un `Dresseur` sans rien changer à cette classe.
|
||||
|
||||
```python
|
||||
def compter_par_type(equipe):
|
||||
"""
|
||||
Compte les Pokémon de chaque type.
|
||||
|
||||
:param equipe: (list) Liste de Pokémon
|
||||
:return: (dict) Dictionnaire {type: nombre}
|
||||
"""
|
||||
compteur = {}
|
||||
for pokemon in equipe:
|
||||
if pokemon.type_pokemon in compteur:
|
||||
compteur[pokemon.type_pokemon] += 1
|
||||
else:
|
||||
compteur[pokemon.type_pokemon] = 1
|
||||
return compteur
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Exercice 10 : Refactoring
|
||||
|
||||
Il n'y a pas de réponse unique. Éléments de discussion :
|
||||
|
||||
- **Avec les sous-classes**, chaque type porte son propre comportement : c'est lisible, et l'on peut donner à un type des particularités qui ne se résument pas à des faiblesses. Mais le code d'`attaquer` est recopié trois fois, et ajouter un type oblige à écrire une nouvelle classe.
|
||||
- **Avec le dictionnaire `FAIBLESSES`**, toutes les règles sont réunies au même endroit et ajouter une faiblesse se fait en une ligne, sans toucher au code. Il gère aussi naturellement un type faible contre plusieurs autres.
|
||||
- Pour des **données** (qui bat qui), le dictionnaire est plus adapté. Les sous-classes sont intéressantes quand les types ont des **comportements** vraiment différents. On peut combiner les deux : des sous-classes qui consultent le dictionnaire.
|
||||
|
||||
---
|
||||
|
||||
Auteurs : Florian Mathieu, Enzo Frémeaux, Timothée Decoster
|
||||
|
||||
Licence CC BY-SA
|
||||
|
||||
Reference in New Issue
Block a user