nsi:terminales:classes
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| nsi:terminales:classes [2021/06/23 18:05] – goupillwiki | nsi:terminales:classes [2022/08/29 21:39] (Version actuelle) – goupillwiki | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| ====== Classes - Programmation orientée objet (POO) ====== | ====== Classes - Programmation orientée objet (POO) ====== | ||
| - | {{: | + | {{nsi: |
| - | {{ : | + | {{ nsi: |
| + | |||
| + | {{ : | ||
| Apparu en 1960 avec LISP. Très répandu aujourd' | Apparu en 1960 avec LISP. Très répandu aujourd' | ||
| Ligne 25: | Ligne 27: | ||
| </ | </ | ||
| - | Dans l'[[classes_exo_preparatoire|exercice]] on a vu que dans un projets grandissant, | + | Dans l'[[classes_exo_preparation|exercice]] on rencontre les problèmes : |
| - | * beaucoup de fonctions, il faut allonger leurs noms pour bien les distinguer, | + | |
| - | * pas facile de contrôler les données sur lesquelles agissent les fonctions. | + | |
| - | Pour le dire simplement, la POO permet | + | * Pas de façon simple pour regrouper toutes les données concernant |
| + | * pas de façon simple de savoir qu'une variable contient un triangle, et un triangle bien formé, | ||
| + | * multiplication de fonctions en vrac. | ||
| + | |||
| + | Les classes vont permettre de simplifier ces problèmes : | ||
| + | |||
| + | * La classe définit un modèle qui définit | ||
| + | * Dès lors qu'un objet est de type '' | ||
| + | * Chaque classe définit ses propres méthodes | ||
| ===== Notion de classe ===== | ===== Notion de classe ===== | ||
| Ligne 39: | Ligne 47: | ||
| <WRAP tip> | <WRAP tip> | ||
| - | Cela rappelle la définition abstraite des structures de données -- [[liste_abstraite|Listes]], | + | Cela rappelle la définition abstraite des structures de données -- [[.structures: |
| </ | </ | ||
| + | ===== Définir une classe ===== | ||
| + | ==== Donner un nom ==== | ||
| - | ## Définir une classe | + | Une classe |
| - | Dans l' | + | Par exemple |
| - | * Pas de façon simple pour regrouper toutes | + | ==== Identifier |
| - | * pas de façon simple de savoir qu'une variable contient un triangle, et un triangle bien formé, | + | |
| - | * multiplication de fonctions en vrac. | + | |
| - | Les classes vont permettre de simplifier ces problèmes : | + | Qu'est ce qui définit un objet ? |
| - | * La classe définit | + | Un triangle sera défini par ses 3 sommets. Ses attributs seront donc ces sommets. Mais sous quelle forme ? |
| + | * 6 variables pour les 3 paires de coordonnées ? | ||
| + | | ||
| + | * 3 objets | ||
| - | * Dès lors qu'un objet est de type `Triangle`, on est certain qu'il respecte les contraintes qu' | + | On a le choix. |
| - | * Chaque classe définit ses propres fonctions de sorte que le code est mieux organisé. | + | ==== Définir l' |
| - | ### Comment | + | Comment |
| - | *Remarque :* par convention, le nom d'une classe utilise | + | On doit bien sûr pouvoir le créer. Un objet aura toujours un **constructeur** qui est une méthode spéciale permettant de le créer -- notamment de réserver l' |
| - | On peut suivre les étapes suivantes : | + | Et puis par exemple, pour un '' |
| - | * Identifier les objets et leurs **attributs** : quelles sont les données caractérisant les objets | + | |
| - | * Identifier les opérations : comment utilise-t-on l'objet, notamment depuis l’extérieur ? | + | |
| - | * Définir la **visibilité** : quels attributs / méthodes | + | |
| - | * Implémentation | + | |
| - | *On reviendra plus tard sur la notion de visibilité.* | + | ==== Choisir |
| - | ### Exercice 2 | + | <WRAP group> |
| + | <WRAP half column> | ||
| + | En général, les classes permettent de régler finement les éléments d'un objet qui sont accessibles depuis l' | ||
| - | Reprenons le cas du triangle. | + | Un élément accessible est dit **public**, s'il est inaccessible, |
| - | * Quels sont ses attributs ? | + | ==== Diagramme UML ==== |
| - | * Quelles sont les opérations possibles ? | + | |
| - | Pour représenter ces choix de façons claire et explicite, on utilise un diagramme UML - *Unified Modeling Language* | + | {{nsi: |
| - | | Triangle | + | Pour aider au développement et au travail de groupe, les informaticiens ont recours à différents types de diagrammes dont le but est de communiquer rapidement les choix effectués. Le UML -- Unified Modeling Language |
| - | |:------------- | | + | |
| + | C'est un vaste domaine, nous allons rester simples. | ||
| + | |||
| + | > Les + signifient " | ||
| + | </ | ||
| + | <WRAP half column> | ||
| + | ^ Triangle | ||
| |**Attributs**| | |**Attributs**| | ||
| | + réel : x1 | | | + réel : x1 | | ||
| Ligne 95: | Ligne 109: | ||
| | + réel : aire() | | | + réel : aire() | | ||
| | + réel : périmètre() | | | + réel : périmètre() | | ||
| + | |||
| + | //diagramme UML// | ||
| + | </ | ||
| + | </ | ||
| Dans un programme complexe, le diagramme UML permettra d' | Dans un programme complexe, le diagramme UML permettra d' | ||
| - | ## Classe en Python | + | ==== Dépendance ==== |
| - | + | ||
| - | Voici un modèle | + | |
| - | </ | + | |
| - | + | ||
| - | <file python triangle.py> | + | |
| - | class Triangle: # on utilise PascalCase | + | |
| - | """ | + | |
| - | Commentaires utiles pour la lisibilité et la documentation | + | |
| - | """ | + | |
| - | x1: float # ceci n'est pas requis en Python | + | |
| - | y1: float # mais peut rendre le code plus clair | + | |
| - | x2: float | + | |
| - | y2: float | + | |
| - | x3: float | + | |
| - | y3: float | + | |
| - | nom: string | + | |
| - | + | ||
| - | def __init__(self, | + | |
| - | """ | + | |
| - | Constructeur - Gère l' | + | |
| - | """ | + | |
| - | self.x1 | + | |
| - | # self.x1 est l' | + | |
| - | self.y1 | + | |
| - | # etc. | + | |
| - | + | ||
| - | def aire(self) -> float : | + | |
| - | """ | + | |
| - | Documentation... | + | |
| - | -> float n'est pas requis en Python. Il permet seulement de préciser ce qui est | + | |
| - | attendu en sortie. | + | |
| - | """ | + | |
| - | + | ||
| - | # formule de maths... | + | |
| - | return abs((self.x2 - self.x1)*(self.y3 - self.y1) - (self.y2 - self.y1)*self(x3 - self.x1))/ | + | |
| - | + | ||
| - | # puis les autres méthodes... | + | |
| - | </ | + | |
| - | + | ||
| - | < | + | |
| - | **Exemple d' | + | |
| - | + | ||
| - | ```python | + | |
| - | monTriangle | + | |
| - | monTriangle.aire() # retourne 7.0 | + | |
| - | type(monTriangle) | + | |
| - | ``` | + | |
| - | + | ||
| - | ### Instanciation | + | |
| - | + | ||
| - | `Parallelogramme` et `Triangle` sont des modèles. Quand on définit la *classe* `Triangle`, on ne crée aucun objet de type `Triangle`. On se contente de dire comment faire pour en créer un ou pour l' | + | |
| - | + | ||
| - | Quand on écrit `monTriangle = Triangle(...)`, | + | |
| - | + | ||
| - | On dit que `monTriangle` est une **instance** de la classe `Triangle`. | + | |
| - | + | ||
| - | > **Autrement dit :** On peut définir ce qu'est une voiture et comment on fait une voiture dans un livre. Ce livre n'en est pas pour autant une voiture. Quand on suit le livre et qu'on fabrique la voiture, on obtient une réalisation de voiture, c'est une **instance** de voiture. | + | |
| - | + | ||
| - | Une classe peut avoir plusieurs instances : on peut créer plusieurs objets `Triangle` en suivant le guide que constitue la classe `Triangle`. | + | |
| - | + | ||
| - | > **Autrement dit :** On peut fabriquer plusieurs voitures, identiques ou pas. | + | |
| - | + | ||
| - | ### Exercice 3 | + | |
| - | + | ||
| - | * Dans un fichier `triangle.py` définissez la classe `Triangle` - **complétez** ce qui manque dans le modèle donné plus haut. | + | |
| - | * En fin de fichier, ajoutez le code de test suivant et exécutez : | + | |
| - | + | ||
| - | ```python | + | |
| - | if __name__ == ' | + | |
| - | monTriangle = Triangle(0, | + | |
| - | a = monTriangle.aire() | + | |
| - | p = monTriangle.perimetre() | + | |
| - | + | ||
| - | print(" | + | |
| - | print(" | + | |
| - | ``` | + | |
| - | + | ||
| - | ### Très important : | + | |
| - | + | ||
| - | * L' | + | |
| - | + | ||
| - | En Python, il s'agit de la méthode `__init__(...)` | + | |
| - | + | ||
| - | * En tant qu' | + | |
| - | * `monTriangle.x1` désigne l' | + | |
| - | * `monTriangle.aire` désigne la méthode `aire` de `monTriangle`. | + | |
| - | + | ||
| - | * Dans la signature et le corps de la méthode `aire`, on peut voire apparaître le mot-clé `self`. | + | |
| - | La méthode `aire` ne peut être appelée que via une **instance**, | + | |
| - | + | ||
| - | ```python | + | |
| - | tA.aire() # dans ce cas, self = tA | + | |
| - | tB.aire() # dans ce cas, self = tB | + | |
| - | ``` | + | |
| - | + | ||
| - | D' | + | |
| - | + | ||
| - | * En Python, **lors de la définition** de la méthode `aire`, on est obligé de préciser l' | + | |
| - | + | ||
| - | Au moment de l' | + | |
| - | + | ||
| - | #### L' | + | |
| - | Sans classe, on faisant `aireTriangle(triangle)` où `triangle` subissait la fonction passivement. | + | |
| - | + | ||
| - | Maintenant, `triangle` est un objet doté de méthodes et on écrit `triangle.aire()`. L' | + | |
| - | + | ||
| - | Chaque type d' | + | |
| - | + | ||
| - | ### Exercice 4 | + | |
| - | + | ||
| - | On peut considérer que le diagramme UML de la classe `Parallelogramme` est identique à ceci près qu'il faut ajouter un quatrième point. | + | |
| - | + | ||
| - | * Dans un fichier `parallelogramme.py` créez une classe `Parallelogramme` | + | |
| - | * En fin de fichier, ajoutez le code de test suivant et exécutez : | + | |
| - | + | ||
| - | ```python | + | |
| - | if __name__ == ' | + | |
| - | monPlg = Parallelogramme(0, | + | |
| - | a = monPlg.aire() | + | |
| - | p = monPlg.perimetre() | + | |
| - | + | ||
| - | print(" | + | |
| - | print(" | + | |
| - | ``` | + | |
| - | + | ||
| - | *On peut voir ici que le code est presque identique à celui du cas `Triangle`. Quand on appelle la méthode `aire()`, aucune confusion n'est possible. `monPlg` est un objet `Parallelogramme`, | + | |
| - | + | ||
| - | * Que faudrait-il faire pour être certain qu'un objet `Paralllelogramme` soit toujours valide ? | + | |
| - | + | ||
| - | *Comprendre : comment vérifier qu'il est valide au moment où on le crée et vérifier qu'il reste valide dans le cas où on modifie ses attributs.* | + | |
| - | + | ||
| - | #### Public / privé | + | |
| - | + | ||
| - | ```python | + | |
| - | plg = Parallelogramme(0, | + | |
| - | plg.x1 = 10 | + | |
| - | ``` | + | |
| - | + | ||
| - | Lors de la création `plg` est bien valide. Mais on modifie `plg.x1` de sorte qu'il ne l'est plus... | + | |
| - | + | ||
| - | Une solution est d' | + | |
| - | + | ||
| - | Un attribut **privé** ne peut-être lu et modifié que depuis l' | + | |
| - | + | ||
| - | *Remarque : En Python, il n'y a pas vraiment de gestion de l' | + | |
| - | + | ||
| - | Dans l' | + | |
| - | + | ||
| - | Dans le diagramme UML, on mettra - au lieu de +. | + | |
| - | + | ||
| - | *Remarque : Certains invitent à utiliser `__` (deux underscore au lieu d'un). Ne vous y fiez pas trop. Ce choix crée des difficultés et ne constitue pas une protection.* | + | |
| - | + | ||
| - | *La notion public / privé n'est pas explicite dans le programme. Ne vous en souciez donc pas trop, on pourra travailler en ne considérant que rien n'est privé.* | + | |
| - | + | ||
| - | ### Classes et sous-classes | + | |
| - | + | ||
| - | * **Éviter tout bloc de code trop compliqué | + | |
| - | * **Idem pour les classes | + | |
| - | + | ||
| - | ### Exercice 5 | + | |
| - | + | ||
| - | * Dans un fichier `point.py`, définir une classe `Point` ayant les attributs `x`, `y`. | + | |
| - | * Ajouter la méthode `distance(self, | + | |
| - | * Modifier les classes `Triangle` et `Parallelogramme` pour qu' | + | |
| - | + | ||
| - | + | ||
| - | ### Important | + | |
| - | ```python | + | |
| - | >>> | + | |
| - | >>> | + | |
| - | >>> | + | |
| - | ``` | + | |
| - | + | ||
| - | Les deux points ont les mêmes coordonnées mais ce sont néanmoins deux points différents. | + | |
| - | + | ||
| - | En écrivant `Point(2, | + | |
| - | + | ||
| - | + | ||
| - | ### Exercice 6 - problème de dépendance | + | |
| - | + | ||
| - | Supposons que l'on veuille ajouter une fonction qui détermine si un point est contenu dans un triangle. Selon vous, quel est le meilleur choix ? | + | |
| - | + | ||
| - | * dans la classe `Point`, définir la méthode `estDansTriangle(self, | + | |
| - | * dans la classe `Triangle`, | + | |
| - | * en dehors des deux classes, définir une fonction `triangleContientPoint(triangle, | + | |
| - | + | ||
| - | ### Dépendance | + | |
| - | Le diagramme UML permet de faire apparaître que la classe `Triangle` utilise la classe `Point`. | + | |
| - | </ | + | |
| - | + | ||
| - | {{ : | + | |
| - | + | ||
| - | < | + | |
| - | ### | + | |
| - | + | ||
| - | Quand on définit `x = 5` et `y = 12`, on peut faire avec `x` et `y` un certains nombres d' | + | |
| - | + | ||
| - | * On peut additionner `x + y` | + | |
| - | * On peut comparer `x <= y` | + | |
| - | * On peut afficher `print(x)`, ce qui provoque le **transtypage** de `x`, `int -> str` | + | |
| - | + | ||
| - | Si on souhaite pouvoir faire ce genre d' | + | |
| - | + | ||
| - | Le cas le plus courant est l' | + | |
| - | + | ||
| - | Il faut utiliser la méthode `__str__(self)` | + | |
| - | + | ||
| - | ```python | + | |
| - | # Dans la classe Point | + | |
| - | def __str__(self): | + | |
| - | """ | + | |
| - | transtypage -> str | + | |
| - | """ | + | |
| - | return "({} ; {})" | + | |
| - | ``` | + | |
| - | + | ||
| - | ### Exercice 7 | + | |
| - | + | ||
| - | Ajoutez une fonction de transtypage vers `str` dans la classe `Triangle`. | + | |
| - | + | ||
| - | Pensez à tester. | + | |
| - | + | ||
| - | ### Exercice 8 | + | |
| - | + | ||
| - | * Proposez une implémentation pour les **piles** en utilisant des classes. | + | |
| - | * Même chose pour les **files**. | + | |
| - | * Dans les deux cas, prévoyez une méthode `__str__` | + | |
| - | + | ||
| - | + | ||
| - | ### Exercice 9 ++ | + | |
| - | + | ||
| - | On peut aller plus loin en ajoutant des vecteurs, en définissant le produit scalaire... | + | |
| - | + | ||
| - | ### Exercice 10 ++ | + | |
| - | </ | + | |
| - | [[classe_relation_exercice|Implémentation d' | + | Supposons que l'on crée une classe '' |
| + | {{ nsi: | ||
nsi/terminales/classes.1624464313.txt.gz · Dernière modification : de goupillwiki
