IPO / A3P(AL) – TP2 2223v1
Sujet
Durée : 3-4h (TP 2.1 + 2.2)
1. Vous devez déjà avoir lu les explications du paragraphe I. sur la page Moodle du TP2(.1).
2. Sauvegardez le fichier compilation.jar (dans Chrome, vous pouvez glisser/déposer ce lien sur la barre d'onglets) dans un sous-répertoire TP2 du répertoire consacré à cette unité, puis ouvrez-le dans BlueJ (Project > Open ZIP/JAR...).
3. Lisez la classe MaPremiereClasse, regardez comment sont programmées/présentées les différentes méthodes. Cette classe n'a d'autre intérêt que de vous montrer un exemple assez complet de ce que l'on trouve à l'intérieur d'une classe, et de vous entraîner à comprendre les messages d'erreur du compilateur.
4. Lisez les commentaires javadoc et les retrouver dans la vision « Documentation » (choisir en haut à droite); dans quel ordre les accesseurs et les modificateurs ont-ils été écrits ?
5. Puis compilez, traduisez-comprenez le message d’erreur, corrigez, et recommencez jusqu’au succès. Si vous ne comprenez pas un mot en anglais, cherchez dans ce glossaire, et s’il n’y est pas, n’hésitez pas à en demander la traduction.
6. Conservez ouverte la fenêtre de cette classe pour vous en inspirer dans les exercices suivants.
7.
Lorsque
vous pensez avoir correctement traité les 2 erreurs qui figuraient dans ce programme,
cliquez-droit sur la classe en vert (MaPremiereClasseTest)
et choisissez Tout tester.
Vous devez voir en haut de la petite fenêtre qui s'affiche
2 lignes commençant par une coche verte.
Si ce n'est pas le cas, cliquez sur la ligne en cause pour lire le message d'erreur du style
"expected : <X> ; was <Y>"
et si vous ne comprenez pas d'où vient le problème, appelez un intervenant.
Nota : le travail demandé doit être terminé, en séance ou, à défaut, hors séance.
Cet exercice va consister à modifier des classes d'un exemple de projet BlueJ : le projet maison
Sauvegarder (dans le répertoire TP2) puis ouvrir le fichier proj_maison.jar .
1. Dans
la fenêtre principale de Bluej,
les flèches entre classes définissent des liens de dépendance. Les flèches en
tireté spécifient un lien "uses".
Comme l'indiquent ces flèches, la classe Maison utilise les classes Cercle, Carre et Triangle, et ces
dernières utilisent la classe Canvas.
Veuillez noter que la classe Maison peut utiliser les classes
Cercle,
Carre, et
Triangle car ces 4 fichiers
.java se trouvent tout simplement dans le même répertoire/dossier.
La classe Canvas définit
des utilitaires de bas niveau pour l'affichage graphique d'objets : nous ne
l'étudierons pas.
2. Après
avoir compilé (si nécessaire), créer un objet Carre [ clic droit sur cette
classe puis choisir new
Carre() ], le rendre visible, et le déplacer de 200 pixels vers le bas
==> invoquer la méthode depVertical [ clic
droit sur l'objet puis void
depVertical( ) ] ;
créer de même un objet Maison et invoquer
la méthode dessine(
) sur cette instance.
L'image affichée illustre que l'objet de type Maison est une composition d'objets de
type Cercle,
Carre et Triangle. Invoquer
maintenant la méthode place.
Une maison ensoleillée apparait-elle ?
Par contre, les déplacements se font
instantanément car les procédures de déplacements lents ne sont pas encore
écrites correctement ; ce sera l’objet de la deuxième partie de ce
tp.
1. Prendre connaissance du code source de la classe Cercle [ double-clic ].
2. Exercice 3.1.3a : Créer dans la classe Cercle la fonction suivante :
o nom : getPosition
o paramètre : aucun
o valeur de retour : la position de l'objet codée sous la forme de l’entier 1000*x + y, où x et y sont les coordonnées du cercle (on supposera avoir toujours : 0 <= coordonnées < 1000).
3. Compiler, créer un objet de type Cercle, puis tester le bon fonctionnement de la méthode getPosition (la méthode doit apparaître grâce à un clic-droit sur l’objet). Comment savez-vous que c’est le bon résultat ? Inspectez le cercle.
4. Exercice 3.1.3b : Créer dans la classe Cercle un deuxième constructeur :
5. Compiler, puis créer un objet de type Cercle à l’aide de ce nouveau constructeur. Pourquoi le cercle n’est-il pas visible ? Voir l’exercice suivant pour résoudre ce problème.
Rappel : On notera que la classe Cercle possède ainsi deux méthodes de même nom : Cercle. Ceci ne crée pas d'ambiguïté car ces deux méthodes ont des signatures différentes. Cette possibilité qu'offre Java est appelée surcharge. Si vous avez du mal, lisez les indices tout en bas.
6. Exercice 3.1.3c : Modifier ce nouveau constructeur pour que le cercle soit automatiquement visible dès sa création. Regarder la méthode rendVisible() pour comprendre pourquoi le cercle n’était pas visible, puis appeler cette méthode plutôt que positionner aEstVisible à true.
7. Compiler, créer un objet Cercle, puis tester le bon fonctionnement de cette nouvelle version. Si vous avez du mal, lisez les indices tout en bas.
8.
Exercice 3.1.3d : Vous remarquerez
que les deux constructeurs comportent chacun 5 affectations des 5 mêmes attributs,
même si ce ne sont pas avec les mêmes valeurs.
Puisque le deuxième constructeur peut mettre n'importe quelle valeur dans les 4 premiers attributs,
il peut en particulier mettre celles qu'y met le premier constructeur.
Donc pour éviter de la duplication de code, il vaudrait mieux que le premier constructeur
se serve du (c-à-d appelle le) deuxième constructeur, en lui passant les 4 valeurs qu'il veut.
La syntaxe pour qu'un constructeur appelle un autre constructeur (de la même classe) est très précise :
this(
paramètres_attendus_par_le_constructeur_appelé );
De plus, cette instruction doit forcément être la première instruction du constructeur.
Faire cette modification pour éviter l'ennemi numéro un en bonne programmation :
la duplication de code !
1. Prendre connaissance du code source de la classe Maison.
2. Exercice 3.1.4a : Modifier la classe Maison de façon à ce que la méthode qui rend l’image visible soit appelée automatiquement à la création de l’objet. Compiler et tester. Tout est bien placé ? Sinon, ajouter ce qu'il faut. Si vous avez du mal, lisez les indices tout en bas.
3.
Exercice 3.1.4b : Modifier
la classe Maison
de façon à ajouter comme 5ème composant du dessin un deuxième soleil.
Faites-en sorte que seule la couleur soit différente par rapport au premier soleil.
Compiler et tester. Pourquoi le premier soleil n’est-il plus visible ?
Mettez maintenant en commentaire une ou deux instructions pour qu'il ne soit plus
à la même place que le premier soleil.
setNoirEtBlanc() et setCouleur() fonctionnent-elles
toujours ? Sinon, corriger et
tester.
4.
Exercice 3.1.4c : Créer dans
la classe Maison
la méthode suivante
sans modifier la classe Cercle , puis compiler et tester.
5. Exercice 3.1.4d : Modifier la classe Maison de façon à ne pas avoir à répéter 2 fois à peu près la même chose dans getPositionsDeuxSoleils(). Pour cela, créer une nouvelle fonction getPositionSoleil() (publique ou privée ?), retournant une String et acceptant un cercle en paramètre, et ne retournant la position que de ce cercle. Ensuite, getPositionsDeuxSoleils() n’a qu’à appeler getPositionSoleil() 2 fois. Compiler et tester. Si vous avez du mal, lisez les indices tout en bas.
6. Exercice
3.1.4e : Modifier la méthode getPositionSoleil() pour qu’elle
accepte en plus un paramètre String contenant le nom (que vous avez choisi) du
cercle dont elle retourne la position ;
1. Exercice 3.1.5a : Ajouter des commentaires de documentation aux méthodes que vous avez développées pour qu'elles soient renseignées au moins au même niveau que les autres. Regarder la « Documentation », puis prendre connaissance de l'arborescence des fichiers générés et, sous navigateur, consulter le fichier index.html.
2. Exercice 3.1.5b : Mêmes étapes pour la classe Maison (une des méthodes n’est pas commentée).
3. Prendre connaissance de l'arborescence des fichiers générée dans le répertoire proj_maison et, sous navigateur, consulter le fichier index.html. Quel est le problème ?
4.
Pour y remédier, [menu Outils,
choix Générer
la documentation du projet]. Attendre suffisamment longtemps,
puis vérifier le résultat en navigant parmi toutes les classes du projet.
1. Dans
la méthode depLentVertical
de la classe Carre,
supprimer l'appel à depVertical()
qui déplace d'un seul coup de plusieurs pixels, et provoquer un déplacement
lent en utilisant un appel récursif de cette méthode avec un appel de depVertical
d’un seul pixel à chaque fois
(se déplacer lentement de N pixels revient à se déplacer
"rapidement" d'un pixel puis à se déplacer lentement de N-1 pixels ;
mais au fait, quand le carré va-t-il arrêter de se déplacer ?).
Pour en savoir plus sur la récursivité, lisez
ce mini-cours.
a) Essayez d’abord avec
pDistance toujours positive. Compiler, tester.
Si vous avez du mal, lisez les indices tout en bas.
b) Essayez ensuite de tenir
compte de la bonne direction (utiliser vDelta en décommentant les premières
lignes des méthodes de déplacements lents). Compiler, tester.
Si vous obtenez une
StackOverflowError, c’est que la récursion ne s’arrête jamais.
[clic droit sur la barre rouge et blanche pour arrêter l’exécution]
2. Reportez vos instructions dans depLentHorizontal en adaptant les noms. Compiler. Tester.
3. Reportez
ces modifications dans les classes Cercle et Triangle. Compiler. Tester. Maison toujours
ensoleillée ?
AIDE : Il est
possible d’afficher les valeurs de vos variables avec
System.out.println(…);
1. Visualisez le « styleguide » de l'outil javadoc :
https://www.oracle.com/technetwork/java/javase/documentation/index-137868.html#tag .
2. Lisez les parties consacrées aux « tags » @author, @version, @param, @return, et @see . Lisez le reste en travail personnel.
3. Exercice 3.2.2a : Ajoutez/complétez (si nécessaire) les commentaires javadoc en incorporant des @author et un @version dans chaque classe, ainsi que le @return et les @param dans chaque méthode. Regénérez la documentation et vérifiez les informations qui y figurent désormais.
Regénérer la javadoc puis sauvegarder le projet Maison [menu Project, choix Save] et envoyer les fichiers sur votre mail personnel. Un peu fastidieux, non ? Alors essayer plutôt [menu Project, choix Create Jar File.../Exporter...] puis envoyer uniquement le fichier .jar ainsi créé. Le destinataire n’aura plus qu’à utiliser [menu Project, choix Open ZIP/JAR...] et à désigner le fichier .jar.
Fermer le projet maison [menu Project, choix Close] , voire BlueJ.
Lire une première fois le guide de style (en anglais) qu’il vous faudra appliquer dans toute l’unité, et pourquoi pas dans la suite de vos études ; sauter certaines notions qui n’ont pas encore été vues.
signature { cas particulier (condition d'arrêt) cas général }
(*) Pour en savoir plus sur la représentation en machine des nombres entiers, lire
ça.
· Avez-vous bien fait TOUS les exercices, dans TOUTES leurs étapes ?
· Avez-vous compris TOUT ce que vous avez vu ? Sinon, demandez à un intervenant.
· Avez-vous
expérimenté le CodePad ? (Essayez
: int i=12;↵ i*2↵ etc…)
· Si vous avez fini avant l’heure prévue, demandez aux intervenants si vous pouvez partir avant la fin du TP ou bien s’ils considèrent que vous avez encore du travail à faire.
· Sinon,
terminez tout en travail personnel avant le prochain tp.
1) Pour faire l'exercice 3.1.3b :
· Dupliquez le constructeur existant. Ajoutez-lui les paramètres indiqués dans l'énoncé. Servez-vous des paramètres dans les instructions. Ça compile ?
· Pour le 6., remplacez les 5 instructions du premier constructeur par this(); et passez-lui dans les parenthèses les bonnes valeurs pour qu'il crée toujours ce cercle bleu de diamètre 30 et de coordonnées (20,60).
2) Pour faire l'exercice 3.1.3c :
· Ne modifiez que le deuxième constructeur (puisque le premier l'appelle).
· N'utilisez pas 2 instructions lorsqu'une seule suffit !
3) Pour faire l'exercice 3.1.4a :
· Cherchez tous les endroits du code où apparaît aSoleil, dupliquez chaque instruction, et adaptez-la pour aSoleil2.
4) Pour écrire la méthode getPositionsDeuxSoleils :
· N’a-t-elle bien aucun paramètre (elle n’a besoin d’aucune information supplémentaire) ?
· Quelle fonction (de la classe Cercle) retourne la position du cercle ?
· Comment extraire d’un nombre de la forme 20060 les coordonnées 20 et 60 (voir aide dans le sujet) ?
· Construire la chaîne de caractères bout après bout en utilisant un + avant chaque bout (de type String ou int) supplémentaire.
5) Pour écrire la méthode getPositionSoleil :
· Relisez l’énoncé pour savoir quel type de valeur cette fonction retourne, et quel est le type de son paramètre.
· Reprenez la moitié de ce que vous avez écrit 2 fois dans la méthode getPositionsDeuxSoleils, mais en appliquant les appels de méthode au cercle passé en paramètre (dans getPositionSoleil) plutôt qu’à un cercle précis (comme this.aSoleil2 par exemple).
· Il ne reste plus qu’à remplacer la majeure partie de getPositionsDeuxSoleils par 2 appels à getPositionSoleil, des deux côtés de la chaîne " | " qui sépare les 2 soleils.
6) Pour écrire les méthodes de déplacement lent (par exemple vertical) par récursivité :
· Respectez pas à pas les étapes proposées dans l’énoncé ; quand on parle d’un déplacement « normal » ou « rapide », on désigne juste un appel à depVertical.
· N’oubliez ni le test d’arrêt (il n’y a plus qu’un seul pixel à parcourir), ni de modifier le paramètre (pour que la distance restant à parcourir diminue à chaque fois).
· Lorsque cela fonctionne vers le bas, intéressez-vous à la variable vDelta (en commentaire) ; au lieu d’enlever 1 au paramètre à chaque fois, ne vaudrait-il pas mieux enlever vDelta (dont la valeur change selon le sens de déplacement souhaité) pour que cela fonctionne aussi vers le haut ?
7) Pour écrire la fonction factorielle :
· n! = n x (n-1)! et par convention 0! = 1 (ne pas s'occuper des entiers négatifs)