Dans cette seconde séance, nous allons voir comment encapsuler les objets. L’objectif est de rendre l’utilisation d’un objet et son implémentation aussi indépendantes que possible pour que les modifications d’implémentation n’aient pas (ou peu) d’impact sur les classes l’utilisant. Nous allons également prendre en main un IDE (Environement de Développement Intégré) qui va nous simplifier l’édition de code Java.
Suivre le tutoriel de prise en main d’Intellij et de Gradle
Attention Une maîtrise minimale de ces deux outils est supposée acquise par la suite.
Nous considérons maintenant que la surface de la planète Mars est décomposée en tuiles carrées (quadrillage). Le robot peut seulement se déplacer de tuile en tuile. La position du robot s’exprime donc maintenant sous forme de coordonnées (x,y)
de type entier
qui représente le numéro de colonne et le numéro de ligne dans le quadrillage. Le fichier Position.java
contenu dans l’archive td2-sample.zip fournit une implémentation minimale de la classe Position
.
1) Modifiez la visibilité des attributs x
et y
en private
. Constatez alors qu’une erreur de visibilité apparait dans la classe Main
.
2) Ajoutez dans la classe Position
les méthodes getX()
et getY()
permettant de récupérer respectivement l’abscisse et l’ordonnée de la position. À noter que ces méthodes ne permettent pas de modifier les attributs, mais fournissent simplement un moyen de récupérer l’information.
3) Modifier la classe Main
pour utiliser ces méthodes.
4) Ajouter les méthodes suivantes vues lors du TD précédent.
void translate(int dx, int dy) { ... }
void translate(int delta) { ... }
Mondialisation Il est important de respecter les standards de codage qui recommandent d’utiliser l’anglais pour permettre au plus grand nombre une relecture aisée du code.
Actuellement, nos méthodes n’ont pas de modificateurs d’accès. L’absence de modificateurs d’accès est en soit un niveau de visibilité, appelé friendly et qui correspond à la visibilité paquetage. Pour faire simple, toutes les classes d’un même répertoire appartiennent au même paquetage. Cependant, il est courant que l’on souhaite rendre disponibles le plus largement possible certaines méthodes. On utilise dans ce cas le modificateur d’accès public
.
Position
soient publiques.Nous allons pour la suite de ce TD prendre en main une base de code un peu plus conséquente qui va permettre d’interagir avec notre robot martien. Pour ce faire, téléchargez l’archive suivante : td2-student. Une fois l’archive décompressée le code est exécutable sans erreur. Par la suite les seules classes à modifier sont les classes Main
et Robot
. Mais il est fortement conseillé de prendre le temps de lire les autres classes.
1) Exécutez le code contenu dans cette archive et repérez graphiquement votre robot.
2) Dans la classe Main
après l’instanciation du robot, ajoutez la ligne position.translate(10);
puis exécuter à nouveau le code. Que constatez-vous ?
3) Comment peut-on rendre le robot indépendant de la variable position
contenu dans la méthode start
de la classe Main
?
4) Proposez une solution en modifiant le constructeur de Robot
.
5) Remplacez maintenant la ligne position.translate(10);
par robot.getPosition().translate(10);
puis exécuter à nouveau le code. Que constatez-vous ?
6) Faites les modifications nécessaires dans la classe Robot
.
7) La classe SpriteRobot
est fournie et ne doit pas être modifiée. Elle est chargée de l’affichage graphique du robot. La classe Robot
ne contient que la modélisation du robot, indépendamment de sa représentation graphique. Complétez les méthodes suivantes de la classe Robot
.
// Rayon d'action du robot
int range();
// Est-ce que le robot peut se déplacer sur la position cible?
boolean canMove(Position target);
// Actions à réaliser lorsque le robot se déplace sur la cible: mise à jour des coordonnées du robot, de son énergie restante, etc.
void move(Position target);
Contrairement au TD précédent, le calcul de la distance entre deux positions se fait maintenant dans la classe Robot
et dans un espace géométrique discret. C’est-à-dire que notre robot ne peut plus se déplacer que de case en case soit horizontalement soit verticalement. Il n’a pas la possibilité de se déplacer en diagonale (c’est un choix qui n’est pas dépendant de l’espace dans lequel il évolue). On dit que le déplacement est en connexité-4.
Pour rappel la méthode distance
permet de calculer la distance entre la position actuelle du robot et la cible à atteindre. Attention cette méthode doit maintenant renvoyer un int
correspondant au nombre de cases à parcourir pour atteindre la cible.
// Distance entre la position actuelle du robot et la cible
int distance(Position target)
1) Modifiez la méthode distance
de la classe Robot
pour qu’elle calcule la distance de manhattan.
2) Testez votre code afin que lors d’un clic de la souris sur une tuile de la surface martienne, le robot se déplace s’il dispose de suffisamment d’énergie pour atteindre la cible.
Notre robot est pour le moment capable de se déplacer instantanément, ce qui n’est pas très réaliste! Nous allons réaliser une animation graphique pour visualiser le déplacement entre la position source et la position cible. Nous utilisons pour cela le code de la méthode animateMove
de la classe SpriteRobot
. Comme vous pouvez le constater, cette méthode utilise la méthode getPathTo
de la classe Robot
. Cette méthode renvoie un tableau de positions sur lesquelles le robot doit se rendre pour atteindre la cible (hors la position source).
1) Fournissez une implémentation simple de la méthode getPathTo
. Le robot se déplace d’abord à l’horizontale, puis à la verticale. Le chemin comporte au plus deux positions.
2) Améliorez le code de votre méthode pour que le déplacement se fasse en escalier.
4) Essayez d’équilibrer les marches de l’escalier (Le robot alterne des déplacements horizontaux et verticaux).
5) Que se passe-t-il lors d’un clic de la souris sur une tuile de la surface martienne si le robot est encore en train de se déplacer?
6) Faites en sorte que le robot ne puisse accepter un nouvel ordre de déplacement que lorsqu’il a terminé le déplacement en cours.