Outils pour utilisateurs

Outils du site


nsi:terminales:classes

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
nsi:terminales:classes [2021/06/23 18:39] goupillwikinsi: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) ======
  
-{{:langages:lisp_logo.png?nolink&50 |Lisp}}+{{nsi:langages:lisp_logo.png?nolink&50 |Lisp}}
  
-{{ :langages:java_logo.png?nolink&50|Java}}+{{ nsi:langages:java_logo.png?nolink&50|Java}} 
 + 
 +{{ :nsi:terminales:classes:classes.fiche.pdf |Fiche à imprimer}}
  
 Apparu en 1960 avec LISP. Très répandu aujourd'hui. En Java, //presque// tout est objet. Apparu en 1960 avec LISP. Très répandu aujourd'hui. En Java, //presque// tout est objet.
Ligne 45: Ligne 47:
  
 <WRAP tip> <WRAP tip>
-Cela rappelle la définition abstraite des structures de données -- [[liste_abstraite|Listes]], [[pile_abstraite|Piles]] et [[file_abstraite|Files]] -- consistant à préciser toutes les propriétés désirées. Une classe est une implémentation qui énonce naturellement les propriétés désirées.+Cela rappelle la définition abstraite des structures de données -- [[.structures:liste_abstraite|Listes]], [[.structures:pile_abstraite|Piles]] et [[.structures:file_abstraite|Files]] -- consistant à préciser toutes les propriétés désirées. Une classe est une implémentation qui énonce naturellement les propriétés désirées.
 </WRAP> </WRAP>
  
Ligne 85: Ligne 87:
 ==== Diagramme UML ==== ==== Diagramme UML ====
  
-{{:langages:uml_logo.png?nolink&100 |}}+{{nsi:langages:uml_logo.png?nolink&100 |}}
  
 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'indiquer les **dépendances** entre les différentes classes. Dans un programme complexe, le diagramme UML permettra d'indiquer les **dépendances** entre les différentes classes.
  
-===== Implémentation Python ===== +==== Dépendance ====
- +
-==== Syntaxe ==== +
- +
-<code python linenums> +
-class NomDeLaClasse: +
-    """ +
-    commentaires décrivant à quoi sert la classe +
-    """ +
-    x:float   # un exemple d'attribut. ":float" pas obligatoire en Python +
-    n:int = 0 # autre exemple, initialisé à 0 +
-     +
-    def une_fonction(self, a, b, c): +
-        """ +
-        Notez l'attribut spécial self qui désigne l'objet lui-même +
-        """ +
-        self.x # "self" désigne l'objet, ".x" désigne l'attribut x de cet objet +
- +
-c = NomDeLaClasse(...) # création d'un objet respectant le modèle définit par la classe +
-c.x # désigne l'attribut x de l'objet c +
-</code> +
- +
- +
- +
- +
- +
- +
- +
- +
-<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, x1, y1, x2, y2, x3, y3, nom): +
-        """ +
-        Constructeur - Gère l'initialisation de l'objet +
-        """ +
-        self.x1 = x1 # x1 est la valeur fournie +
-                     # self.x1 est l'attribut x1 de l'objet +
-        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... +
-</file> +
- +
- +
-**Exemple d'utilisation** +
- +
-```python +
-monTriangle = Triangle(0,0,5,2,3,4,'T1'+
-monTriangle.aire() # retourne 7.0 +
-type(monTriangle)  # retourne Triangle, ce qui s'affiche <class : Triangle>  +
-``` +
- +
-### 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'utiliser. +
- +
-Quand on écrit `monTriangle = Triangle(...)`, on crée un objet de type `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__ == '__main__': +
-    monTriangle = Triangle(0,0,5,2,3,4,'T1'+
-    a = monTriangle.aire() +
-    p = monTriangle.perimetre() +
-     +
-    print("L'aire du triangle est de {}".format(a)) +
-    print("Le périmètre du triangle est de {}".format(p)) +
-``` +
- +
-### Très important : +
- +
-* L'instanciation `monTriangle = Triangle(...)` provoque l'exécution du **constructeur**. +
- +
-  En Python, il s'agit de la méthode `__init__(...)`  +
- +
-* En tant qu'objet de type `Triangle`, `monTriangle` a des attributs et des méthodes. +
-  * `monTriangle.x1` désigne l'attribut `x1̀ de `Triangle` +
-  * `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**, par exemple `monTriangle.aire()`. `self` désigne alors l'instance elle-même. +
- +
-```python +
-tA.aire() # dans ce cas, self = tA +
-tB.aire() # dans ce cas, self = tB +
-``` +
- +
-  D'autres langages préfèrent utiliser le mot-clé `this`. +
- +
-* En Python, **lors de la définition** de la méthode `aire`, on est obligé de préciser l'argument `self` en première position. +
- +
-  Au moment de l'appel, on ne précise pas `self`. On se contente de *par ex* `tA.aire()`, et `self` est automatiquement mis égal à `tA`. Tout se passe comme si on avait appelé `Triangle.aire(tA)`. +
- +
-#### L'objet est reponsable de l'action +
-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'objet est **responsable** du calcul. +
- +
-Chaque type d'objet définit ses propres méthodes. Le code devient plus clair : `triangle.aire()`, `rectangle.aire()`. C'est léger, lisible, bien organisé. +
- +
-### 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__ == '__main__': +
-    monPlg = Parallelogramme(0,0,5,2,8,6,3,4,'P1'+
-    a = monPlg.aire() +
-    p = monPlg.perimetre() +
-     +
-    print("L'aire du plg. est de {}".format(a)) +
-    print("Le périmètre du plg. est de {}".format(p)) +
-``` +
- +
-*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`, donc `monPlg.aire()` appelle la méthode `aire` de `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,0,1,0,1,1,1,0,'P'+
-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'empêcher la modification de l'attribut `x1` (et des autres) en le rendant **privé**. +
- +
-Un attribut **privé** ne peut-être lu et modifié que depuis l'intérieur de la définition de la classe. +
- +
-*Remarque : En Python, il n'y a pas vraiment de gestion de l'accès public / privé. On convient de nommer les attributs / méthodes privé(e)s en les faisant précéder par `_`.* +
- +
-Dans l'exemple, ce serait donc `_x1`. +
- +
-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é  :** découper au maximum en fonctions. +
-* **Idem pour les classes  :**  Utiliser une classe spécifique pour tout type d'item. +
- +
-### Exercice 5 +
- +
-* Dans  un fichier `point.py`, définir une classe `Point` ayant les attributs `x`, `y`. +
-* Ajouter la méthode `distance(self, autrePoint)` de sorte que pour les `Point` `A` et `B`, l'expression `A.distance(B)` donne la distance `AB`. +
-* Modifier les classes `Triangle` et `Parallelogramme` pour qu'elles utilisent la classe `Point` au lieu des paires de coordonnées `x, y`. +
- +
- +
-### Important +
-```python +
->>> p1 = Point(2,3) +
->>> p2 = Point(2,3) +
->>> p1 == p2 # la réponse est False ! +
-``` +
- +
-Les deux points ont les mêmes coordonnées mais ce sont néanmoins deux points différents. +
- +
-En écrivant `Point(2,3)` on crée un **instance** en mémoire. Quand on réécrit `Point(2,3)` on crée une nouvelle instance en mémoire même si elle a les mêmes attributs. Ce sont donc deux instances différentes. +
- +
- +
-### 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, triangle)` +
-* dans la classe `Triangle`,  définir la méthode `contientPoint(self, point)` +
-* en dehors des deux classes, définir une fonction `triangleContientPoint(triangle, point)` +
- +
-### Dépendance en UML +
-Le diagramme UML permet de faire apparaître que la classe `Triangle` utilise la classe `Point`. +
-</markdown> +
- +
-{{ :nsi:terminales:umltrianglepoint.png?nolink&400 |}} +
- +
-<markdown> +
-###Méthodes magiques +
- +
-Quand on définit `x = 5` et `y 12`, on peut faire avec `x` et `y` un certains nombres d'opérations qui seront comprises automatiquement par le langage. +
- +
-* 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'opérations avec notre objet, c'est possible ! +
- +
-Le cas le plus courant est l'affichage. On aimerait que le transtypage `str(monPoint)` produise une chaîne de caractère comme `(15 ; 45)` pour le point de coordonnées `x 15` et `y 45`. +
- +
-Il faut utiliser la méthode `__str__(self)` +
- +
-```python +
-# Dans la classe Point +
-def __str__(self): +
-    """ +
-    transtypage -> str +
-    """ +
-    return "({} ; {})".format(self.nom, self.x, self.y) +
-``` +
- +
-### 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 ++ +
-</markdown>+
  
-[[classe_relation_exercice|Implémentation d'une relation (BDD) avec les classes]]+Supposons que l'on crée une classe ''Point'' pour gérer les points et qu'alors ''Triangle'' utilise cette classe. On peut faire apparaître clairement la dépendance sur le diagramme UML.
  
 +{{ nsi:terminales:classes:umltrianglepoint.png?nolink&400 |}}
nsi/terminales/classes.1624466362.txt.gz · Dernière modification : de goupillwiki