Dans ce TP, on s'intéresse au concept d'héritage et de polymorphisme. Pour cela, on cherchera à développer un logiciel permettant de créer et d'afficher des figures géométriques plus ou moins complexes via divers afficheurs graphiques. Les compétences travaillées durant cette activité sont les suivantes :
- Comprendre et décrire des interfaces logicielles
- Comprendre et utiliser l'héritage
- Comprendre et utiliser le polymorphisme
20 min
Figure 1 (ci-dessous) : Diagramme de classes représentant des formes 2D.
classDiagram
direction TB
class Shape2D {
# xpos : int
# ypos : int
# color : tuple[int]
+ area() float
+ draw() void
+ move(deltaX : int, deltaY : int) void
+ get_xy() tuple[int, int]
}
class Point {
+ area() float
+ draw() void
}
class Circle {
-radius : int
+area() float
+draw() void
}
class Rectangle {
-width : int
-height : int
+area() float
+draw() void
}
Shape2D <|-- Circle
Shape2D <|-- Rectangle
Shape2D <|-- Point
Etant donné le diagramme de classes ci-dessus représentant des formes 2D, répondre aux questions suivantes :
-
L'attribut radius est-il accessible pour un objet Rectangle ?
-
Un objet Circle possède-t-il un attribut color
-
Peut-on appliquer la méthode move à un objet Point ?
-
Grâce à quelle notion de l'approche objet, la méthode area peut-elle être présente dans toutes les classes du diagramme et à quoi sert cette notion ?
-
Quelle hypothèse doit-on considérer pour rendre la classe Shape2D abstraite ?
1h30
Formes simples
-
Traduire les classes ci-dessus en python. On veillera à ce que les points suivants soient respectés:
- Une classe = un fichier.
- Les constructeurs sont correctement implémentés.
- Le nomage des attributs et méthodes privés ou protégés respecte les conventions python.
-
Les méthodes
area,moveetget_xysont correctement implémentés. -
La méthode
drawlève une exception de typeNotImplementedErrorcar elle sera implémentée plus tard dans le TP (voir exemple ci-dessous). -
(Optionnel) Les types sont déclarés selon la norme PEP 483.
-
Faire en sorte que l'appel du constructeur par défaut de la classe
Circlerenvoie une instance de cercle de rayon 10 en position x=0 et y=0. -
Dans le fichier
partieII.py, implémenter la fonctionrun_question_4. Cette fonction:- utilise le constructeur par défaut pour créer un cercle
- affiche son aire
- crée un rectangle de longueur 30 et de largeur 10 en position (10, 10)
- le déplace en positon (15, 20)
- affiche ses coordonnées x, y
Tester la fonction en lançant le script
python partieII.py q4.
Formes composées
-
Proposer une extension à votre code permettant d'obtenir une forme 2D composée de plusieurs autres formes 2D. On considère que l'aire de la forme 2D composée est la somme des aires des formes 2D individuelles. On pourra nommer notre forme composée
CombinedShape2D. -
Dans le fichier
partieII.py, implémenter la fonctionrun_question_6permettant de:- construire une forme 2D composée de deux cercles et d'un rectangle au choix
- afficher l'aire de cette forme
- afficher les coordonnées de cette forme
- appliquer une translation de 20 pixels en x et 8 pixels en y
Tester la fonction en lançant le script
python partieII.py q6.
1h30
Dans cette partie on s'intéresse à l'affichage de formes géométriques.
Affichage dans le terminal
-
Créer l'interface python
Displayerrespectant les spécifications ci-dessous.LoadingclassDiagram direction TB class Displayer { + draw_point(x: int, y: int, color: Color): void + draw_line(x1: int, y1: int, x2: int, y2: int, color: Color): void + draw_circle(x: int, y: int, radius: int, color: Color): void + draw_rectangle(x: int, y: int, width: int, length: int, color: Color): void + draw_square(x: int, y: int, side: int, color: Color): void } <<interface>> Displayer -
Créer la classe
ShellDisplayerqui implémente l'interfaceDisplayeret affiche dans le terminal des messages de la forme:FormeName(x=X, y=Y, attr1=ATTR1, attr2=ATTR2, ..., attrN=ATTRN, color=(R, G, B))Exemple :
Circle(x=10, y=5, radius=20, color=(0, 0, 255)) -
Modifier la méthode
drawde l'interfaceShape2Dpour quelle accepte en paramètre un afficheur quelconque. -
Implémenter les méthodes
drawdes classesPoint,Line,Circle,Rectangle,SquareetCombinedShape2D. -
Dans le fichier
partieIIII.py, compléter la fonctionrun_question_5. Tester. -
Créer une classe
Smileyqui est une forme composée de 3 cercles (1 pour le visage et 2 pour les yeux), un carré pour le nez et un rectangle pour la bouche.On fera attention à ce que l'utilisation suivante soit valide.
displayer = ShellDisplayer() smiley = Smiley(x=100, y=50, size=45, color=(20, 20, 20)) smiley.draw(displayer)
Exécuter la commande
python partieIII.py q6pour vérifer.
Affichage partagé
On souhaite désormais afficher nos formes sur un écran partagé sur le web. Le site draw.david-albert.fr est un tableau interactif un peu particulier. Pour y dessiner une forme il faut utiliser une requête HTTP de type POST.
La documentation de l'API du tableau interactif est donné dans le fichier DOC.md.
-
Installer la bibliothèque
requestsqui permet d'exécuter des requêtes HTTP. -
Créer une classe
WebDisplayerqui implémente l'interfaceDisplayerdans le but d'afficher des formes géométriques sur le tableau interactif. -
Dans le ficher
partieIII.py, implémenter la fonctionrun_question_9. Le programme demande à l'utilisateur d'indiquer le numéro de l'écran d'affichage puis, en continue, lui demande trois 3 valeurs (x, y et size) et affiche le smiley correspondant. Dès que l'utilisateur entre la chaîne"q", le programme s'arrête.Tester
python partieIII.py q9 -
Améliorer l'affichage de votre bonhomme et prenez une capture d'écran (à joindre dans le dossier de restitution).
30 min
Modifier l'architecture du logiciel actuel pour faire en sorte que l'on puisse sauvegarder une forme 2D quelconque dans un fichier JSON. On fera également en sorte de pouvoir reconstruire une forme depuis un fichier précédemment créé.
Aide : Un dictionnaire python peut être simplement transcrit au format JSON en utilisant la fonction dumps du module json.
Vous pouvez dès à présent commencer le TP n°4 sur la conception logicielle avec UML.