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:39] – 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 45: | 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: |
| </ | </ | ||
| Ligne 85: | Ligne 87: | ||
| ==== Diagramme UML ==== | ==== Diagramme UML ==== | ||
| - | {{: | + | {{nsi: |
| 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 -- en fait partie. | 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 -- en fait partie. | ||
| Ligne 114: | Ligne 116: | ||
| Dans un programme complexe, le diagramme UML permettra d' | Dans un programme complexe, le diagramme UML permettra d' | ||
| - | ===== Implémentation Python ===== | + | ==== Dépendance ==== |
| - | + | ||
| - | ==== Syntaxe ==== | + | |
| - | + | ||
| - | <code python linenums> | + | |
| - | class NomDeLaClasse: | + | |
| - | """ | + | |
| - | commentaires décrivant à quoi sert la classe | + | |
| - | """ | + | |
| - | x: | + | |
| - | n:int = 0 # autre exemple, initialisé à 0 | + | |
| - | + | ||
| - | def une_fonction(self, | + | |
| - | """ | + | |
| - | Notez l' | + | |
| - | """ | + | |
| - | self.x # " | + | |
| - | + | ||
| - | c = NomDeLaClasse(...) # création d'un objet respectant le modèle définit par la classe | + | |
| - | c.x # désigne l' | + | |
| - | </ | + | |
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | <file python triangle.py> | + | |
| - | class Triangle: # on utilise PascalCase = UpperCamelCase | + | |
| - | """ | + | |
| - | 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 = x1 # x1 est la valeur fournie | + | |
| - | # self.x1 est l' | + | |
| - | self.y1 = 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 = Triangle(0, | + | |
| - | 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.1624466362.txt.gz · Dernière modification : de goupillwiki
