AP3 - programmation orientée objet en...

50
Arnaud PÊCHER Université de Bordeaux 1 (LaBRI) http://www.labri.fr/pecher/pmwiki/pmwiki.php/Teaching/2012 AP3 - programmation orientée objet en Java DUT Informatique support de cours basé sur celui de Mickaël Montassier (2011-2012) 2012-2013

Transcript of AP3 - programmation orientée objet en...

Page 1: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

Arnaud PÊCHERUniversité de Bordeaux 1 (LaBRI)

http://www.labri.fr/pecher/pmwiki/pmwiki.php/Teaching/2012

AP3 - programmation orientée objet en JavaDUT Informatique

support de cours basé sur celui de Mickaël Montassier (2011-2012)

2012-2013

Page 2: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,
Page 3: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

Table des matières

1 Semaines 1 & 2 : héritage, polymorphisme, transtypage, classes abstraites et interfaces 11.1 Semaine 1 : présentation de Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.1.1 Préambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.1.2 Premiers pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.1.3 Génération automatisée de la documentation : javadoc . . . . . . . . . . . . . . . . . . . 21.1.4 Eléments de la syntaxe via l’exemple "Bicycle" . . . . . . . . . . . . . . . . . . . . . . . 3

1.1.4.1 Déclaration d’une classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.1.4.2 Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.1.4.3 Déclaration des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.1.4.4 Instanciation des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.1.4.5 Libération des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.1.4.6 Déclaration d’une méthode . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.1.4.7 Méthodes statiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.1.5 Héritage, polymorphisme, transtypage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.1.6 Classes abstraites et interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.1.7 Exercice à rendre en fin de séance (par binôme) . . . . . . . . . . . . . . . . . . . . . . . 10

1.2 Semaine 2 : application - modélisation d’un labyrinthe . . . . . . . . . . . . . . . . . . . . . . . 12

2 Semaines 3 & 4 : interfaces graphiques en SWING 152.1 Semaine 3 : la librairie graphique SWING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.1.1 Composants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.1.2 Component vs. Container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.1.3 Gestionnaire d’affichage/LayoutManager . . . . . . . . . . . . . . . . . . . . . . . . . . 162.1.4 Exemple : fenêtre principale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.1.5 Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.1.6 Réponse aux événements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.1.7 Exercice : changement de couleur d’une ellipse lors d’un clic . . . . . . . . . . . . . . . . 192.1.8 Exercice à rendre : le jeu de Taquin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.2 Semaine 4 : applications - modifications de l’interface graphique du labyrinthe . . . . . . . . . . . 27

3 Semaines 5 & 6 : exceptions, collections 293.1 Semaine 5 : exceptions et collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

3.1.1 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293.1.1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293.1.1.2 Synthèse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323.1.1.3 Compléments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323.1.1.4 Exercice : ThrowTest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.1.2 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343.1.2.1 L’interface Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343.1.2.2 Prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343.1.2.3 Les listes doublement chaînées . . . . . . . . . . . . . . . . . . . . . . . . . . 353.1.2.4 les vecteurs ou tableaux dynamiques . . . . . . . . . . . . . . . . . . . . . . . 36

3

Page 4: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

4 TABLE DES MATIÈRES

3.1.2.5 Les tables de hachage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363.1.2.6 les collections ordonnées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363.1.2.7 Les vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363.1.2.8 Opérations de masse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373.1.2.9 Algorithmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

3.1.3 Exercice à rendre : tri des arcs d’un graphe . . . . . . . . . . . . . . . . . . . . . . . . . 373.2 Semaine 6 : application - mode multi-personnages et exceptions ExceptionSortie . . . . . . 37

4 Semaines 7 & 8 : JUnit, sérialisation, RMI 414.1 Semaine 7 : cours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

4.1.1 JUnit : tests unitaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414.1.2 Sérialisation : objets persistants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

4.1.2.1 L’interface Serializable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424.1.2.2 La classe ObjectOutputStream . . . . . . . . . . . . . . . . . . . . . . . . . . 424.1.2.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424.1.2.4 La classe ObjectInputStream . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

4.1.3 RMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434.1.3.1 RMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434.1.3.2 Instanciation de l’objet distant . . . . . . . . . . . . . . . . . . . . . . . . . . . 434.1.3.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444.1.3.4 Coté client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444.1.3.5 Gestionnaire de sécurité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

4.2 Semaine 8 : application finale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

Page 5: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

Chapitre 1

Semaines 1 & 2 : héritage, polymorphisme,transtypage, classes abstraites et interfaces

L’objet de cette partie est de présenter le modèle objet utilisé par Java : notions d’objets, de classes, d’instances,héritage, super-classe, sous-classe, polymorphisme, transtypage, classes abstraites et interfaces.

Cette première partie est volontairement longue : vous avez déjà vu ces notions dans le cadre de la découvertedu langage C++. Il s’agît donc ici d’un survol de ces notions, avec la mention des principales particularités deJava.

L’ensemble des fichiers de cette séance est disponible dans : /net/Bibliotheque/AP3/TD01/code/

Sommaire1.1 Semaine 1 : présentation de Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.1.1 Préambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.1.2 Premiers pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.1.3 Génération automatisée de la documentation : javadoc . . . . . . . . . . . . . . . . . . 21.1.4 Eléments de la syntaxe via l’exemple "Bicycle" . . . . . . . . . . . . . . . . . . . . . . 31.1.5 Héritage, polymorphisme, transtypage . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.1.6 Classes abstraites et interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.1.7 Exercice à rendre en fin de séance (par binôme) . . . . . . . . . . . . . . . . . . . . . . 10

1.2 Semaine 2 : application - modélisation d’un labyrinthe . . . . . . . . . . . . . . . . . . . . . 12

1.1 Semaine 1 : présentation de Java

Java est un langage de programmation orienté objet (POO). Voici quelques avantages et particularités de Java :

– portabilité via une Machine virtuelle– robustesse avec notamment une gestion de la mémoire simplifiée (ramasse miette)– rapidité de développement grâce à des librairies (API - Application Programming Interface) performantes

et variées– publication sur internet - Applets, Services webs– documentation automatique via l’utilitaire javadoc– programmation réseau simplifiée– etc

Java propose pour cela une plateforme logicielle complète (une plateforme est un environnement sur lequel unprogramme tourne) composée de

1

Page 6: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

2CHAPITRE 1. SEMAINES 1 & 2 : HÉRITAGE, POLYMORPHISME, TRANSTYPAGE, CLASSES ABSTRAITES ET INTERFACES

– une machine virtuelle : Java Virtual Machine (JVM) permettant d’exécuter (sans recompilation) un pro-gramme java sur n’importe quel système d’exploitation, du moment que la JVM soit installée. L’installationd’une JVM consiste à déployer un environnement d’exécution : Java Runtime Environment (JRE)

– Java Application Programming Interface - API (composants logiciels - packages) : ce qui permet de ne paspartir de zéro et de proposer rapidement des programmes avancés.

1.1.1 Préambule

Quelques rappels : un objet possède un état (ce sont les données ; au niveau programmation, on parle alorsdes champs, des attributs de l’objet) et un comportement (il s’agit des fonctionnalités associées à l’objet ; auniveau programmation on parle alors de méthodes, de requêtes).

Quelques avantages : modularité, encapsulation, implémentation cachée (réduire les erreurs possibles par lesprogrammes clients), réutilisation du code, ...

Une classe peut être vue comme le plan de montage et le manuel (données, fonctionnalités et implémentation)d’un objet. Une instance est quant à elle la réalisation d’un objet.

1.1.2 Premiers pas

Commençons par le traditionnel “hello world” :

Exemple : HelloWorldApp.java

$> geany HelloWorldApp.java

class HelloWorldApp {public static void main(String[] args){

System.out.println("I’m a small program");}

}

$> javac HelloWorldApp.java$> java HelloWorldApp

Commentaires :

1. la compilation est prise en charge par la commande javac. Cet utilitaire gère les dépendances : si vousavez plusieurs classes à compiler, un javac *.java suffit (pas de makefile à écrire) ;

2. le fichier binaire généré est HelloWorldApp.class : il n’est pas directement exécutable par le systèmed’exploitation, car écrit dans un assembleur simplifié, appelé bytecode, qui sera interprété par la JVM ;

3. la commande java permet de lancer l’exécution d’un programmen en bytecode par la machine virtuelle :le point de départ du programme étant fourni par la méthode main.

En Java, tout est objet à l’exception des types de base (int, float etc). Chaque type de base possèdenéanmoins une classe associée, permettant de le manipuler comme un objet classique. Par exemple, pour le typeint, il s’agît de la classe Integer.

1.1.3 Génération automatisée de la documentation : javadoc

La commande javadoc permet de générer une documentation du code au format HTML. Pour se faire, ellese base sur les commentaires dans le code, définis par /** ... */, ainsi que des mots-clefs prédéfinis, dont lesplus usuels sont :

– @author [author name] : pour identifier les auteurs de la classe– @version [version] : version de la classe

Page 7: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

1.1. SEMAINE 1 : PRÉSENTATION DE JAVA 3

– @param [argument name] [argument description] : description d’un paramètre d’une mé-thode - describes an argument of method or constructor.

– @return [description of return] : description du paramètre retourné par une méthodeVoici l’exemple HelloWorld commenté pour la javadoc :

/** Description of HelloWorldAppDocumented** @author Robert Bidochon* @author Raymonde Bidocho* @version 6.0z Build 9000 Jan 3, 2000*/

public class HelloWorldAppDocumented{

/** Description of main(String[] args)* @param args array of the command line arguments* @return nothing

*/public static void main(String[] args){

System.out.println("I’m a Simple Program");}

}

Générons la documentation associée dans un sous-répertoire doc/ :

$> javadoc HelloWorldAppDocumented.java -author -version -d doc

Il ne reste plus qu’à ouvrir le répertoire doc/ dans un navigateur web pour visualiser et parcourir la docu-mentation générée.

1.1.4 Eléments de la syntaxe via l’exemple "Bicycle"

Considérons maintenant un exemple un peu plus complexe, modélisant une bicyclette, dont nous allons expli-quer la syntaxe ensuite :

Exemple : Bicycle.java

// Fichier Bicycle.javapublic class Bicycle {

private int cadence;private int gear;private int speed;public Bicycle(int startCadence, int startSpeed, int startGear) {

gear = startGear;cadence = startCadence;speed = startSpeed;

}public void setCadence(int newValue) {

cadence = newValue;}public void setGear(int newValue) {

gear = newValue;}public void applyBrake(int decrement) {

speed -= decrement;}public void speedUp(int increment) {

Page 8: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

4CHAPITRE 1. SEMAINES 1 & 2 : HÉRITAGE, POLYMORPHISME, TRANSTYPAGE, CLASSES ABSTRAITES ET INTERFACES

speed += increment;}public void printStates() {

System.out.println("cadence:"+cadence+" speed:"+speed+" gear:"+gear);

}}

// fichier BicycleDemo.javaclass BicycleDemo {

public static void main(String[] args) {

// Create two different Bicycle objectsBicycle bike1 = new Bicycle(1,20,10);Bicycle bike2 = new Bicycle(2,40,60);

// Invoke methods on those objectsbike1.setCadence(50);bike1.speedUp(10);bike1.setGear(2);bike1.printStates();

bike2.setCadence(50);bike2.speedUp(10);bike2.setGear(3);bike2.setCadence(60);bike2.speedUp(10);bike2.setGear(4);bike2.printStates();

}}

Essayons :

$> javac *.java$> java BicycleDemo

Cet exemple va nous servir de base pour expliquer les principaux éléments de la syntaxe de Java.

1.1.4.1 Déclaration d’une classe

La visibilité d’une classe peut être définie à l’aide d’un mot-clef précédant class :

[rien, public, final, abstract] class MyClass {//field, constructor, and method declarations

}

La signification de ces mots-clefs est la suivante :– rien : accessible uniquement au sein du paquet (package)– public : accessible par tout le monde– final : la classe ne peut pas être dérivée (pas de classe fille)– abstract : classe abstraite (ne peut pas être intanciée)Le nom de la classe peut être suivi également d’autres mots-clefs : extends (héritage), implements (implémen-

tation d’interface).

Par exemple :

Page 9: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

1.1. SEMAINE 1 : PRÉSENTATION DE JAVA 5

public class MyClass extends MySuperClass implements YourInterface {//field, constructor, and method declarations

}

Ainsi la classe Bicycle est publique tandis que BicycleDemo ne l’est pas. Comme Bicycle est pu-blique, Java impose que son code soit dans un fichier de nom Bicycle.java. D’une manière générale, il estrecommandé de toujours appliquer cette convention, y compris pour les classes qui ne sont pas publiques.

1.1.4.2 Package

Un paquet (package) est un ensemble de classes réunies dans un répertoire. On déclare le paquet (qui peut êtreun sous-paquet d’un paquet) avec le mot-clef package. Par exemple, pour déclarer une classe dans le sous-paquetmonpackage du paquet coucou, on écrit en première ligne du code source de la classe :

package coucou.monpackage;

Il est possible d’utiliser ces classes via un import :

import coucou.monpackage.*

À noter : coucou est un répertoire contenant le sous-répertoire monpackage. Les binaires (les fichiers.class) doivent être placés dans le répertoire correspondant à leur paquet. Les fichiers sources (.java) ne sontpas soumis à cette contrainte.

Si vous ne spécifiez pas explicitement un paquet pour une classe, celle-ci est implicitement affectée au paquetpackage : ainsi, toute classe appartient à un paquet.

1.1.4.3 Déclaration des variables

Prototype de déclaration d’une variable :

[Specificateur acces][Specificateurs particuliers] Type NomVariable ;

Spécificateur d’accès :– public : accessible depuis partout où la classe est accessible ;– private : accessible uniquement depuis la classe elle-même ;– protected : accessible depuis la classe elle-même et ses classes filles ;– rien (package private) : accessible uniquement depuis les classes du paquet.

Spécificateurs particuliers :– rien– static : définit une variable de classe (et non d’instance).– final : impose l’initialisation lors de la déclaration, ne peut pas être modifié.

Type :– type primitif :

byte (0) [8 bits -128 ... 127],short (0) [16 bits -32768 ... 32767],int (0) [32 bits -2147483648 ... 2147483647],long (0L) [64 bits -9223372036854775808 ... 9223372036854775807],float (0.0f) [single-precision 32-bit IEEE 754 floating point],double (0.0d) [double-precision 64-bit IEEE 754 floating point],boolean (false) [true | false],char(’\u0000’) [single 16-bit Unicode character ’\u0000’ ... ’\uffff’].

– variable objet : String, Object, Integer, Bicycle ...Par exemple :

Page 10: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

6CHAPITRE 1. SEMAINES 1 & 2 : HÉRITAGE, POLYMORPHISME, TRANSTYPAGE, CLASSES ABSTRAITES ET INTERFACES

Bycicle b;String s = " Ouaouh!";int n = 7;

1.1.4.4 Instanciation des variables

Types primitifs :

{int i; // i est declare, instancie et vaut 0

// (valeur par defaut des int)int j = i; // j est declare, instancie et vaut 0

// j est distinct de ii++; // i vaut 1 et j vaut toujours 0

}// i et j sont liberes

Variable objet : c’est une référence sur un objet ; la déclaration d’une variable objet n’instancie pas l’objet(référence null). L’instanciation s’effectue via l’opérateur new.

{Coucou c1; // c1 est une reference nulle sur un

objet coucouc1 = new Coucou(); // appel explicite du constructeur par

defautCoucou c2 = new Coucou("Hi"); // declaration, instanciation

constructeur avec parametresCoucou c3; // c3 est une reference nulle sur un

objet coucouc3= new Coucou ("Ni hao"); // appel explicite du constructeur

// avec parametres}

Attention :

C++ | Java|

Coucou c1 ; | Coucou c1 ;// c1 est un objet Coucou | // c1 est une reference nulle// Appel implicite du constructeur | // sur une objet Couou// par defaut |

| c1 = new Coucou() ;Coucou c2 = c1 ; | // appel explicite du constructeur// Appel du constructeur par copie | // par defaut// DEUX objets distincts |

| Coucou c2 = c1 ;Coucou c3 ; | // copie de la referencec3 = c2 ; | // UN SEUL objet// affectation |// TROIS objets distincts | Coucou c3 ;

| c3 = c1 ;| // copie de la reference| // UN SEUL objet

Page 11: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

1.1. SEMAINE 1 : PRÉSENTATION DE JAVA 7

1.1.4.5 Libération des variables

Il n’y a rien à faire car le Ramasse-miettes (Garbage Collector) se charge de tout.

1.1.4.6 Déclaration d’une méthode

Syntaxe :

[Specif. d’acces][Specif. particuliers] TypeDeRetour NomMethode ([parametres]) [exceptions]

{...

}

Spécificateurs d’accès : rien, public, private, protected (même signification que pour une variable)Spécificateurs particuliers : rien, final (la méthode ne peut pas être redéfinie dans une classe fille), static (méthodestatique - cf ci-après)

Exemple :

public double calculateAnswer(double w, int n, double l, double g){

return (w+l-g);}

Les paramètres sont passés par valeur :– dans le cas d’un type de base, une copie de la donnée est mise à disposition de la méthode - il s’agit d’un

passage en entrée ;– dans le cas d’un objet, une copie de la référence originale est effectuée : la méthode accède donc directement

à l’objet et peut modifier la valeur de ses variables/attribut - il s’agit donc d’un passage en entrée-sortie.Comme en C++, il peut y avoir des méthodes de même nom, mais de signatures différentes (paramètres de

types différents ou objet retourné de type différent) : il s’agit de la surcharge d’une méthode.

1.1.4.7 Méthodes statiques

Une méthode statique (ou méthode de classe) est une méthode qui n’accède qu’aux variables statiques del’objet et qu’à d’autres méthodes statiques. Déclarer une méthode comme statique permet au compilateur de fairedes optimisations particulières.

Syntaxe pour l’appel d’une méthode statique :

ClassName.methodName(args)

Exemple de méthode statique (méthode getNumberOfBicycles retournant le nombre de bicyclettes quiont été instanciées) :

public class Bicycle{private int cadence;private int gear;private int speed;private int id;private static int numberOfBicycles = 0;public Bicycle(int startCadence, int startSpeed, int startGear){

gear = startGear;cadence = startCadence;speed = startSpeed;// increment number of Bicycles and assign ID number

Page 12: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

8CHAPITRE 1. SEMAINES 1 & 2 : HÉRITAGE, POLYMORPHISME, TRANSTYPAGE, CLASSES ABSTRAITES ET INTERFACES

id = ++numberOfBicycles;}// return the ID instance variablepublic int getID() {

return id;}public static int getNumberOfBicycles() {

return numberOfBicycles;}

public String toString(){return "Bicycle "+id;

}...

Par exemple, on peut donc appeler la méthode getNumberOfBicycles avec le code :

int nb = Bicycle.getNumberOfBicycles();

1.1.5 Héritage, polymorphisme, transtypage

Le mot-clef pour l’héritage est extends. Il n’y a pas d’héritage multiple : une classe ne peut avoir qu’uneseule classe mère. La hiérarchie d’héritage forme donc un arbre. La racine de l’arbre est la classe Object (i.e.toute classe hérite de la classe Object).

La classe Object possède quelques méthodes, qui sont donc disponibles pour l’ensemble des classes :– public String toString() : cette méthode permet d’obtenir une représentation de l’objet sous

forme d’une chaine de caractères (par défaut : l’adresse mémoire de l’objet).– public boolean equals (Object o) : cette méthode permet de comparer un objet à l’objet cou-

rant pour savoir s’ils sont égaux ou non (par défaut : elle se base sur les adresses mémoires des objets).– protected Object clone() : cette méthode permet d’obtenir une copie de l’objet et non pas une

copie de la référence vers l’objet (par défaut : copie bit-à-bit des variables de type de base).Nous avons défini un Bicycle. Comment définir un MountainBike, un RoadBike, un TandemBike ? Cel sont

tous des Bicycles avec de nouvelles caractéristiques, propres à chacun.

Faisons hériter le classe MountainBike de la classe Bicycle. (rappelons que la classe MountainBike sera unefille de la classe Bicycle. Bicycle est quant à elle la classe mère de la classe MountainBike.)

public class MountainBike extends Bicycle {

// the MountainBike subclass adds one fieldpublic int seatHeight;

// the MountainBike subclass has one constructorpublic MountainBike(int startHeight, int startCadence,

int startSpeed, int startGear) {super(startCadence, startSpeed, startGear);seatHeight = startHeight;

}

// the MountainBike subclass adds one methodpublic void setHeight(int newValue) {

seatHeight = newValue;}

Page 13: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

1.1. SEMAINE 1 : PRÉSENTATION DE JAVA 9

public String toString(){return "MountainBike "+getID();

}

}

Rappelons, que dans une classe fille, une méthode masque une méthode de la classe mère si elle possède lamême signature que celle-ci : on dit qu’elle redéfinit ou spécialise la méthode correspondante de la classe mère. Enjava, la méthode la plus spécialisée est toujours exécutée (ce qui reviendrait en C++ à déclarer toutes les méthodescommes virtuelles) : c’est ce que l’on appelle le polymorphisme.

Ainsi le code ci-dessous afficherait "MountainBike 1" bien que la variable b soit déclarée de typeBicycle (pour l’affichage, b est converti implicitement en chaine de caractères, via la méthode toString) :

Bicycle b = new MountainBike(1,2,3,4);System.out.println(b);

1.1.6 Classes abstraites et interfaces

Commençons par quelques rappels sur les classes abstraites :– Une classe abstraite ne peut pas être instanciée.– Toute classe contenant une méthode abstraite est abstraite et doit être déclarée comme telle (avec le mot-clefabstract).

– Une classe peut être définie comme abstraite sans contenir de méthodes abstraites (ceci empèche de l’ins-tancier).

– Une classe abstraite peut être implémentée en partie ou en totalité.– Une classe fille d’une classe abstraite ne peut être instanciée que si elle implémente toutes les méthodes

abstraites de sa classe mère (abstraite).– Une classe fille qui n’instancie qu’en partie les méthodes abstraites de sa classe mère (abstraite) est abstraite.En java, une classe ne peut avoir qu’une seule classe mère (héritage simple) contraiement à C++ qui autorise

l’héritage multiple. L’héritage multiple est utile quand une nouvelle classe veut ajouter un nouveau comportementet garder la plupart ou tout l’ancien comportement. Mais quand il y a plus d’une classe mère, des problèmessurviennent quand le comportement d’une classe mère est héritée de deux manières concurrentes.

Considérons par exemple, l’héritage "diamant" : X et Y héritent de W ; Z hérite de X et Y . Supposonsque W contienne un champs publique coucou et soit zref une référence sur un objet Z. À quoi correspondzref.coucou ? Coucou de X , coucou de Y ? Les problèmes d’héritage multiple surviennent d’un héritage mul-tiple d’implémentation. Java fournit un moyen d’hériter un contrat sans hériter l’implémentation : les interfaces.

Une classe est un mélange de conception et d’implémentation. Une interface est une abstraction de pureconception : uniquement des constantes et des méthodes abstraites, aucune implémentation. Chacun peut donneralors sa propre implémentation d’une interface. Une classe peut implémenter plusieurs interfaces. Une interfacepeut étendre, par héritage, une autre interface.

Exemple - les interfaces Personnage, Labyrinthe et SalleUn labyrinthe est formé d’un ensemble de salles. Dans le labyrinthe, on peut placer un héros à l’entrée ou

l’informer s’il est à la sortie. De plus, on peut déterminer l’ensemble des salles dans lesquelles le héros peutse déplacer à partir de sa position courante. Vérifier que l’interface ci-dessous permet de spécifier toutes cesfonctionnalités.

public interface Labyrinthe {// cree le labyrinthe a partir d’un fichierpublic void creerLabyrinthe(String file);

// place bob a l’entree du labyrinthepublic void entrer(Personnage bob);

Page 14: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

10CHAPITRE 1. SEMAINES 1 & 2 : HÉRITAGE, POLYMORPHISME, TRANSTYPAGE, CLASSES ABSTRAITES ET INTERFACES

// fait sortir bob, s’il est a la sortiepublic boolean sortir(Personnage bob);

// renvoie les salles accessibles pour bobpublic Collection<Salle> sallesAccessibles(Personnage bob);

// accesseur sur les salles du labyrinthespublic Collection<Salle> getSalles();

// accesseurs sur l’entreepublic Salle getEntree();

// accesseur sur la sortiepublic Salle getSortie();

}

Pour permettre au héros de se déplacer dans le labyrinthe, une salle peut recevoir le héros :

public interface Salle {public boolean recevoir(Personnage bob);

}

Enfin, le héros peut choisir une salle parmi les salles accessibles, et des accessseurs sont disponibles sur saposition :

public interface Personnage {// renvoie une salle parmi sallesAccesiblespublic Salle faitSonChoix(Collection<Salle> sallesAccessibles);

// renvoie sa position courantepublic Salle getPosition();

// definit sa position courantepublic void setPosition( Salle s);

}

1.1.7 Exercice à rendre en fin de séance (par binôme)

Dans cet exercice, nous allons aborder une modélisation d’un labyrinthe, qui sera exploitée dans le cadre duprojet.

Un graphe est une structure mathématique permettant de modéliser le réseau routier par exemple : il est forméd’un ensemble de sommets (un sommet=une ville dans l’exemple) et d’arcs (un arc=un tronçon routier d’une villea vers un ville b). On dit que deux sommets a et b sont adjacents s’il existe un arc de a à b, ou de b à a. Pourplus d’informations sur les graphes, consulter le cours en ligne de Christophe Rapine : http://www.g-scop.inpg.fr/~rapinec/Graphe/

Considérons les 3 classes Sommet, Arc et Graphe qui proposent une implémentation très simpliste de lastructure de graphes (noter au passage la syntaxe pour parcourir des collections d’objets - nous reviendrons dessusdans un autre cours) :

public class Sommet {}

public class Arc {public Sommet a;

Page 15: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

1.1. SEMAINE 1 : PRÉSENTATION DE JAVA 11

public Sommet b;

public Arc( Sommet a, Sommet b){this.a=a; this.b=b;

}}

public class Graphe {public ArrayList<Sommet> sommets=new ArrayList();public ArrayList<Arc> arcs=new ArrayList();

public boolean estAdjacent(Sommet u, Sommet v){for (Arc arc: arcs){

if ((arc.a==u)&&(arc.b==v)) return true;if ((arc.a==v)&&(arc.b==u)) return true;

}return false;

}}

Ecrire une classe abstraite LabyrintheGraphe héritant de la classe Graphe et implémentant l’interfaceLabyrinthe à l’exception de la méthode creerLabyrinthe.

Besoin d’un peu d’aide ? Voici une solution partielle :

public abstract class LabyrintheGraphe extends Graphe implements Labyrinthe{protected SalleSommet entree;protected SalleSommet sortie;

public abstract void creerLabyrinthe(String file); // to be done : afile format is needed ...

public void entrer(Personnage bob){entree.recevoir(bob);

}

public boolean sortir(Personnage bob){return (bob.getPosition()==sortie);

}

public Collection<Salle> sallesAccessibles(Personnage bob){Collection<Salle> sa = new ArrayList();SalleSommet s = (SalleSommet) bob.getPosition();for (Sommet u : sommets)

if (estAdjacent(u,s))sa.add((Salle) u);

return sa;}

public Collection<Salle> getSalles(){return (Collection) sommets;

}

public SalleSommet getEntree()

Page 16: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

12CHAPITRE 1. SEMAINES 1 & 2 : HÉRITAGE, POLYMORPHISME, TRANSTYPAGE, CLASSES ABSTRAITES ET INTERFACES

{return entree;

}

public SalleSommet getSortie(){

return sortie;}

}

Vous avez bien évidemment observé que la classe SalleSommet est manquante : en faisant appel à votreesprit de déduction, écrivez-la.

Documentez abondamment cette classe et les interfaces Personnage, Salle et Labyrinthe. Générezla javadoc associée et regroupez l’ensemble de la javadoc ainsi que vos classes dans une seule archive auformat zip. Envoyez l’archive par mail à votre chargé de TDs.

S’il vous reste du temps, commencez l’application ci-après ...

1.2 Semaine 2 : application - modélisation d’un labyrinthe

Nous allons mettre en application l’ensemble des notions présentées à travers la création d’un labyrinthe. Pourcette séance, vous êtes entièrement libre pour concevoir votre application. En particulier, vous devez proposer unearchitecture radicalement différente de celle introduite dans la partie précédente ...

Imaginons la situation suivante : notre héros, nommons-le Bob, est perdu au milieu d’un labyrinthe, il leparcourt en passant de salle en salle. Son but est bien sur de trouver la sortie.

Prenez dix minutes avant de lire la suite. Que feriez-vous afin de modéliser cette situation ? Quels choix feriez-vous ? Ces choix sont-ils motivés par l’implémentation ? Toute conception commence avec une feuille de brouillonet un stylo.

Nous allons commencer par une approche “bas niveau” orientée par des choix d’implémentation (on est àl’opposé de la démarche de conception), moins souple que celle reposant sur la structure de graphe vue dans lasection précédente.

Considérons le labyrinthe comme un damier sur lequel on peut poser des jetons correspondant aux salles dulabyrinthe. On peut passer d’une salle à une autre si et seulement si les deux jetons correspondants sont adjacentssur le damier (4 adjacences possibles : haut, bas, gauche, droite). Le labyrinthe possède une unique salle d’entréeet une unique salle de sortie. À partir d’une salle, on est capable de connaitre l’ensemble des salles adjacentes (cequi paraît naturel, il suffit de regarder par la porte).

Etape 1 Pour cette première étape, un exemple de solution vous est fourni : essayez cependant de proposervotre propre solution, en ne réutilisant que la classe Lire (qui vous permet de lire des entrées au clavier del’utilisateur).

1. Proposer une architecture permettant de déplacer Bob à travers le labyrinthe. Le but est ici d’avoir unearchitecture modulable, étendable, facile à maintenir. Vous pourrez utiliser la classe Lire afin de demanderà l’utilisateur la direction de Bob. Bob devra pouvoir connaitre dans quelle salle il se trouve et quelles sallessont adjacentes. Bob commence dans la salle d’entrée du labyrinthe et n’a pas connaissance de la salle desortie. Il sait s’il a gagné que lorsqu’il est dans la salle de sortie.

2. Implémentez, testez.

Page 17: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

1.2. SEMAINE 2 : APPLICATION - MODÉLISATION D’UN LABYRINTHE 13

Etape 2 Dans la suite il n’est plus autorisé de modifier les classes déjà écrites. Vous allez devoir enrichirl’architecture afin de répondre aux nouvelles contraintes.

3. Notre héros a maintenant des points de vie et certaines salles sont piégées. Quand Bob passe dans une sallepiégée, il perd un point de vie. Enrichissez, implémentez, testez.

Etape 34. Certaines salles sont verrouillées ; d’autres contiennent une clef que notre héros a maintenant la possibilité

de ramasser. Enrichissez, implémentez, testez.

Page 18: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

14CHAPITRE 1. SEMAINES 1 & 2 : HÉRITAGE, POLYMORPHISME, TRANSTYPAGE, CLASSES ABSTRAITES ET INTERFACES

Page 19: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

Chapitre 2

Semaines 3 & 4 : interfaces graphiques enSWING

L’objet de cette partie est une introduction à la programmation d’une interface graphique en Java.

L’ensemble des fichiers de cette séance est disponible dans :/net/Bibliotheque/AP3/TD02/code/

Il existe deux grandes librairies graphiques : SWING, la librairie "officielle" développée initialement par Sun,et SWT, la librairie développée initialement par IBM, conjointement avec la plateforme de développement Eclipse.SWING est une solution entièrement en Java, qui s’exécute donc au sein de la machine virtuelle, tandis que SWTfait appel au gestionnaire de fenêtre du système d’exploitation. Ceci permet donc à SWT d’offrir de meilleuresperformances et une meilleure intégration de l’application dans le système d’exploitation (par exemple pour réuti-liser les boites de dialogue prédéfinies comme celle pour l’impression ...). Cependant, les interfaces graphiques enSWING offre une meilleure portabilité.

Dans ce cours, nous n’utiliserons que SWING, sachant que la programmation en SWT est assez similaire.Pour comprendre le fonctionnement d’une interface graphique, les développements seront faits en ligne de com-mande. Naturellement, il existe des outils de développement qui permettent de développer une interface graphiqueen SWING ou SWT de manière graphique. Le plus performant est la plateforme de développement en Java "offi-cielle", à savoir netbeans.

2.1 Semaine 3 : la librairie graphique SWING

Une interface graphique est constituée de composants graphiques (boutons, menus, fenêtres,...) disposésdans des conteneurs (cadres, panneaux, ...) munis d’un gestionnaire de placement, capables de réagir à des évè-nements (souris, clavier).

En Java, les fonctionnalités des composants, conteneurs, gestionnaires de placements et évènements sont dé-crites dans les interfaces ou les classes :

– Component (composants) ;– Container (conteneurs) ;– LayoutManager (gestionnaires de placement) ;– EventListener (écouteurs)SWING constitue un ajout à une librairie plus ancienne : AWT (Abstract Window Toolkit). Pour développer

une interface graphique, on utilise donc des classes ou interfaces issues d’AWT, ou bien des versions plus récentesfournies par SWING, le cas échéant. D’une manière générale, les classes de SWING sont préfixées par la lettreJ : par exemple, la classe JButtion (SWING) est à utiliser de préférence à la classe Button (AWT).

Pour importer ces librairies, il faut écrire :

15

Page 20: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

16 CHAPITRE 2. SEMAINES 3 & 4 : INTERFACES GRAPHIQUES EN SWING

import java.awt.*;import javax.swing.*;

2.1.1 Composants

Les composants sont les briques élémentaires d’une interface graphique. Quelques exemples :

– JLabel : texte non modifiable– JTextField : ligne de texte éditable– JButton : bouton– JMenu : menu– ...

2.1.2 Component vs. Container

Un Container est un Component qui possède la particularité de pouvoir contenir d’autres Component. Parexemple, les JComponent sont des Container. Il est possible d’imbriquer des conteneurs et de construire unehiérarchie d’objets graphiques.

Pour ajouter un composant x dans un conteneur y, il suffit d’utiliser la méthode add :

y.add(x);

Quelques conteneurs :

– JPanel : très simple, convient pour recevoir des boutons,...– JFrame : fenêtre avec titre et bordures– JDialog : permet d’obtenir une entrée de l’utilisateur– ...

2.1.3 Gestionnaire d’affichage/LayoutManager

L’interface LayoutManager est implémentée par un certain nombre de classes de AWT. Un LayoutManagergère la disposition des composants dans un conteneur.

Les principaux LayoutManager sont :

– FlowLayout : arrange les composants de gauche à droite– BorderLayout : dispose les composants dans les régions - north, south, east, west, center– GridLayout : arrange les éléments sur une grille.

Un conteneur possède un attribut LayoutManager affecté par défaut : FlowLayout pour JPanel, BorderLayoutpour JPanel, ... Il est possible de changer le LayoutManager d’un conteneur : par exemple,

p.setLayout(new BorderLayout());

ou de faire l’agencement à la main :

p.setLayout(null);x.setLocation(a,b); // ou x.setBounds(a,b,c,d);x.setSize(c,d)

Page 21: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

2.1. SEMAINE 3 : LA LIBRAIRIE GRAPHIQUE SWING 17

2.1.4 Exemple : fenêtre principale

Dans cet exemple, nous allons créer une fenêtre principale par héritage. Naturellement, on pourrait le faireaussi par délégation.

import java.awt.*;import javax.swing.*;

public class Fenetre extends JFrame {private JButton b1, b2;private JLabel lbl;

public Fenetre(String titre){super(titre);setBounds(0,0,400,200);b1=new JButton("B1");b2=new JButton("B2");lbl=new JLabel("texte quelconque");add(b1,"North");add(lbl,"Center");add(b2,"South");setVisible(true);

}

public static void main(String[] args){Fenetre f=new Fenetre("Exemple 1");

}}

2.1.5 Graphics

La classe java.awt.graphics est une classe abstraite. Elle représente le contexte graphique permettant de des-siner sur un composant.

Il est possible d’obtenir le contexte graphique d’un composant x par :

x.getGraphics();

Il est alors possible de dessiner dans le contexte graphique :

drawOval(int x, int y, int w, int h)drawLine(int x1, int y1, int x2, int y2)drawRect(int x, int y, int w, int h)setColor(Color c)

Considérons un petit exemple : dans une fenêtre, ajoutons un Canvas dans lequel sera dessinée une ellipse.

// Fenetre.javaimport java.awt.*;import javax.swing.*;

public class Fenetre extends JFrame {private Canvas can;

public Fenetre(String titre){super(titre);

Page 22: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

18 CHAPITRE 2. SEMAINES 3 & 4 : INTERFACES GRAPHIQUES EN SWING

setBounds(0,0,400,200);can=new Canvas();add(can,"Center");setVisible(true);Graphics g = can.getGraphics();g.setColor(Color.black);g.drawOval(160,10,65,100);

}}

Bizarre... L’ellipse apparaît une fraction de seconde et disparait.

En fait quand un conteneur s’affiche ou se réaffiche, il appelle sa méthode paint(Graphics g) qui appelle laméthode paint(Graphics g) de chacun des composants présents dans le conteneur. Or la méthode paint de Canvasremplit le dessin de blanc... Que faire ?

Une réponse possible : Il faut alors créer une classe Dessin dérivée de Canvas et redéfinir la méthode paintde Canvas dans cette classe.

// Dessin.javaimport java.awt.*;

public class Dessin extends Canvas{public void paint (Graphics g) {

super.paint(g);g.setColor(Color.black);g.drawOval(10,10,150,100);

}}

// Fenetre.javaimport java.awt.*;import javax.swing.*;

public class Fenetre extends JFrame {private Dessin dessin;

public Fenetre(String titre){super(titre);setBounds(0,0,400,200);dessin=new Dessin();add(dessin,"Center");setVisible(true);

}}

2.1.6 Réponse aux événements

Principes :– Dans certaines circonstances (clic souris, touche pressée, etc), un composant crée un objet événement.– Un contrôleur est un objet capable de traiter un événement.– Il suffit d’associer un contrôleur à un composant pour gérer les événements.Un gestionnaire d’événements (ou contrôleur) est une instance d’une classe qui implémente une interface

dérivée de EventListener.

Page 23: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

2.1. SEMAINE 3 : LA LIBRAIRIE GRAPHIQUE SWING 19

Il existe différents contrôleurs en fonction de la nature des événements à traiter : ActionListener, MouseLis-tener, MouseMotionListener,...

Exemple de classe décrivant une réaction à un clic de la souris :

class BoutonClic implements ActionListener {public void actionPerformed(ActionEvent e){

System.out.println("clic");}

}

Il faut ensuite instancier un gestionnaire d’événements approprié et l’associer au composant concerné :

b.addActionListener(new BoutonClic())

Grâce à cette association, lorsque le composant b émettra un ActionEvent, cet événement sera traité par leBoutonClic qui exécutera sa méthode actionPerformed.

2.1.7 Exercice : changement de couleur d’une ellipse lors d’un clic

Dans une fenêtre, ajoutons deux boutons et une ellipse. En réponse au clic sur le premier bouton, l’ellipsechange de couleur et devient rouge. En réponse au clic sur le second bouton, l’ellipse retrouve sa couleur initiale.Dans un premier temps essayez de le faire seul.

Un peu d’aide ?

// ChangeCouleur.javaimport java.awt.event.*;import java.awt.*;

public class ChangeCouleur implements ActionListener{private Color couleur;private Dessin dessin;

public ChangeCouleur(Color couleur,Dessin dessin){this.couleur=couleur;this.dessin=dessin;

}

public void actionPerformed(ActionEvent e){dessin.setColor(couleur);dessin.repaint();

}}

// Dessin.javaimport java.awt.*;

public class Dessin extends Canvas{private Color couleur;n

public void setColor(Color couleur){this.couleur=couleur;

}

public void paint (Graphics g){

Page 24: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

20 CHAPITRE 2. SEMAINES 3 & 4 : INTERFACES GRAPHIQUES EN SWING

super.paint(g);g.setColor(couleur);g.drawOval(10,10,150,100);

}}

// Fenetre.javaimport java.awt.*;import javax.swing.*;

public class Fenetre extends JFrame {private JButton b1, b2;private Dessin dessin;

public Fenetre(String titre){super(titre);setBounds(0,0,400,200);b1=new JButton("B1");b2=new JButton("B2");dessin=new Dessin();b1.addActionListener(new ChangeCouleur(Color.red,dessin));b2.addActionListener(new ChangeCouleur(dessin.getForeground(),

dessin));add(b1,"North");add(dessin,"Center");add(b2,"South");setVisible(true);

}}

2.1.8 Exercice à rendre : le jeu de Taquin

Vous allez réaliser le jeu en 4 étapes. Pour chacune de ces étapes, il est conseillé de lancer l’éxécutable Taquindisponible dans :/net/Bibliotheque/AP3/TD02/code/02-taquin/Etape-0?/

Vous devez rendre cet exercice par binôme, sous la forme d’une seule archive au format zip, incluant lajavadoc (pensez à bien documenter votre code).

Étape 1. Dessiner une grille vide. Une grille est un Canvas qui possède les attributs suivant : nbLignes,nbColonnes, abs, ord.

Étape 2. Ajouter une classe Jeton : un Jeton possède une position dans la grille, un numéro, une couleur.Ajouter dans Grille une structure de données permettant de stocker l’ensemble des jetons.

Étape 3. Ajouter une classe Click étendant MouseInputAdapter (implémentation par défaut de MouseInput-Listener) qui permet de déplacer les jetons.

Étape 4. Ajouter les boutons de contrôle - ajout/suppresion d’une ligne, ajout/suppression d’une colonne, ré-initialisation - ainsi que la gestion des évènements associés à chaque clic.

Un peu d’aide ? (pour les 3 premières étapes)

Page 25: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

2.1. SEMAINE 3 : LA LIBRAIRIE GRAPHIQUE SWING 21

Correction Étape 1 .

// Grille.javaimport java.awt.*;import javax.swing.*;

public class Grille extends Canvas {private int nbLignes;private int nbColonnes;private int abs;private int ord;final static int largeurColonne = 40;final static int hauteurLigne = 40;

public Grille(int nbLignes, int nbColonnes,int abs, int ord){

this.nbLignes = nbLignes;this.nbColonnes = nbColonnes;this.abs = abs;this.ord = ord;

}// Override paintpublic void paint(Graphics g){

super.paint(g);g.setColor(Color.black);

// dessin de la grillefor(int i=0;i<nbLignes;i++){

for(int j=0;j<nbColonnes;j++){g.drawRect(abs+j*largeurColonne,ord+i*

hauteurLigne,largeurColonne,hauteurLigne);

}}

}}

// Taquin.javaimport java.awt.*;import javax.swing.*;

public class Taquin extends JFrame {private Grille grille;private int nbLignesTaquin;private int nbColonnesTaquin;final static int largeurFenetre = 400;final static int hauteurFenetre = 400;

public Taquin(String titre){super(titre);nbLignesTaquin = 3;nbColonnesTaquin = 3;setBounds(0,0,largeurFenetre,hauteurFenetre);

Page 26: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

22 CHAPITRE 2. SEMAINES 3 & 4 : INTERFACES GRAPHIQUES EN SWING

int x_0 = (largeurFenetre - Grille.getLargeurColonne()*nbColonnesTaquin)/2;

int y_0 = (hauteurFenetre - Grille.getHauteurLigne()*nbLignesTaquin)/2;

grille=new Grille(nbLignesTaquin,nbColonnesTaquin,x_0,y_0);add(grille,"Center");setVisible(true);

}public static void main (String args []){

new Taquin("Jeu de Taquin");}

}

Correction Étape 2 .

// Jeton.java

public class Jeton {private int abs;private int ord;private int numero;private Color couleur;

public Jeton(int abs,int ord,int numero,Color couleur) {this.abs = abs;this.ord = ord;this.numero = numero;this.couleur = couleur;

}public int getAbs(){

return abs;}public int getOrd(){

return ord;}public int getNumero(){

return numero;}public Color getCouleur(){

return couleur;}

}

// Grille.javaimport java.awt.*;import javax.swing.*;

public class Grille extends Canvas{private int nbLignes;private int nbColonnes;private int abs;private int ord;final static int largeurColonne = 40;

Page 27: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

2.1. SEMAINE 3 : LA LIBRAIRIE GRAPHIQUE SWING 23

final static int hauteurLigne = 40;private Jeton jetons [][];private int nbJetons;

public Grille(int nbLignes, int nbColonnes,int abs, int ord)

{this.nbLignes = nbLignes;this.nbColonnes = nbColonnes;this.abs = abs;this.ord = ord;nbJetons = nbLignes * nbColonnes - 1;jetons = new Jeton[nbLignes][nbColonnes];int pas = 256/(nbJetons+2); // pas top...int num=0;for(int i=0;i<nbLignes;i++)

for(int j=0;j<nbColonnes;j++){jetons[i][j]=new Jeton(abs+j*largeurColonne,

ord+i*hauteurLigne,num++,new Color(100,num*pas,num*pas));

}jetons[nbLignes-1][nbColonnes-1]=null;

}// Override paintpublic void paint(Graphics g){

super.paint(g);// dessin des jetonsfor(int i=0;i<nbLignes;i++)

for(int j=0;j<nbColonnes;j++){if(jetons[i][j]!=null){

g.setColor(jetons[i][j].getCouleur());g.fillRect(jetons[i][j].getAbs(),jetons[i][j].

getOrd(),largeurColonne,hauteurLigne);

g.setColor(Color.BLACK);g.drawString(""+jetons[i][j].getNumero(),

(int)(jetons[i][j].getAbs()+largeurColonne/2),

(int)(jetons[i][j].getOrd()+hauteurLigne/2));

}}

// dessin de la grilleg.setColor(Color.black);for(int i=0;i<nbLignes;i++)

for(int j=0;j<nbColonnes;j++)g.drawRect(abs+j*largeurColonne,ord+i*hauteurLigne,

largeurColonne,hauteurLigne);

}}

Page 28: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

24 CHAPITRE 2. SEMAINES 3 & 4 : INTERFACES GRAPHIQUES EN SWING

// Taquin.javaimport java.awt.*;import javax.swing.*;

public class Taquin extends JFrame {private Grille grille;private int nbLignesTaquin;private int nbColonnesTaquin;final static int largeurFenetre = 400;final static int hauteurFenetre = 400;

public Taquin(String titre){super(titre);nbLignesTaquin = 4;nbColonnesTaquin = 4;setBounds(0,0,largeurFenetre,hauteurFenetre);int x_0 = (largeurFenetre - Grille.getLargeurColonne()*

nbColonnesTaquin)/2;int y_0 = (hauteurFenetre - Grille.getHauteurLigne()*nbLignesTaquin

)/2;grille=new Grille(nbLignesTaquin,nbColonnesTaquin,x_0,y_0);add(grille,"Center");setVisible(true);

}public static void main (String args []){

new Taquin("Jeu de Taquin");}

}

Correction Étape 3 .

// Click.javaimport javax.swing.event.*;import java.awt.event.*;import javax.swing.*;

public class Click extends MouseInputAdapter {private Grille grille;

public Click(Grille g){grille=g;

}public void mouseClicked(MouseEvent e){

int absClick = e.getX();int ordClick = e.getY();grille.deplacerJeton(absClick,ordClick);grille.validate();grille.repaint();

}}

// Jeton.java

Page 29: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

2.1. SEMAINE 3 : LA LIBRAIRIE GRAPHIQUE SWING 25

import java.awt.*;public class Jeton{

private int abs;private int ord;private int numero;private Color couleur;

public Jeton(int abs,int ord,int numero,Color couleur){this.abs = abs;this.ord = ord;this.numero = numero;this.couleur = couleur;

}public Jeton(Jeton j){

abs=j.abs;ord=j.ord;numero=j.numero;couleur=j.couleur;

}// Ajouter mutateurs si besoin

}

// Grille.javaimport java.awt.*;import javax.swing.*;

public class Grille extends Canvas{private int nbLignes;private int nbColonnes;private int abs;private int ord;final static int largeurColonne = 40;final static int hauteurLigne = 40;private Jeton jetons [][];private int nbJetons;private int i_null;private int j_null;

public Grille(int nbLignes, int nbColonnes,int abs, int ord){

this.nbLignes = nbLignes;this.nbColonnes = nbColonnes;this.abs = abs;this.ord = ord;nbJetons = nbLignes * nbColonnes - 1;jetons = new Jeton[nbLignes][nbColonnes];int pas = 256/(nbJetons+2); // pas top...int num=0;for(int i=0;i<nbLignes;i++)

for(int j=0;j<nbColonnes;j++){jetons[i][j]=new Jeton(abs+j*largeurColonne,

ord+i*hauteurLigne,num++,

Page 30: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

26 CHAPITRE 2. SEMAINES 3 & 4 : INTERFACES GRAPHIQUES EN SWING

new Color(100,num*pas,num*pas));}

jetons[nbLignes-1][nbColonnes-1]=null;j_null = nbLignes-1;i_null = nbColonnes-1;

}// Ajouter mutateurs si besoin// Override paintpublic void paint(Graphics g){

// super.paint(g);// dessin des jetonsfor(int i=0;i<nbLignes;i++)

for(int j=0;j<nbColonnes;j++){if(jetons[i][j]!=null){

g.setColor(jetons[i][j].getCouleur());g.fillRect(jetons[i][j].getAbs(),jetons[i][j].

getOrd(),largeurColonne,hauteurLigne);

g.setColor(Color.BLACK);g.drawString(""+jetons[i][j].getNumero(),

(int)(jetons[i][j].getAbs()+largeurColonne/2),

(int)(jetons[i][j].getOrd()+hauteurLigne/2));

}}

// dessin de la grilleg.setColor(Color.black);for(int i=0;i<nbLignes;i++)

for(int j=0;j<nbColonnes;j++)g.drawRect(abs+j*largeurColonne,ord+i*hauteurLigne,

largeurColonne,hauteurLigne);}public void deplacerJeton(int x,int y){

// trouver le jetonint i_jeton=x-abs;int j_jeton=y-ord;if( i_jeton >= 0 && i_jeton < nbColonnes*largeurColonne &&

j_jeton >= 0 && j_jeton < nbLignes*hauteurLigne){i_jeton/=largeurColonne;j_jeton/=hauteurLigne;

}else

return;//verifier l’adjacence et si ok permutterif((i_null == i_jeton && j_null == j_jeton+1) ||

(i_null == i_jeton && j_null == j_jeton-1) ||(i_null == i_jeton+1 && j_null == j_jeton) ||(i_null == i_jeton-1 && j_null == j_jeton)){

Jeton tmp = jetons[j_jeton][i_jeton];jetons[j_jeton][i_jeton]=null;jetons[j_null][i_null]=tmp;jetons[j_null][i_null].setAbs(abs+i_null*largeurColonne);

Page 31: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

2.2. SEMAINE 4 : APPLICATIONS - MODIFICATIONS DE L’INTERFACE GRAPHIQUE DU LABYRINTHE 27

jetons[j_null][i_null].setOrd(ord+j_null*hauteurLigne);i_null=i_jeton;j_null=j_jeton;

}}

}

// Taquin.javaimport java.awt.*;import javax.swing.*;

public class Taquin extends JFrame {private Grille grille;private int nbLignesTaquin;private int nbColonnesTaquin;final static int largeurFenetre = 400;final static int hauteurFenetre = 400;private Click click;

public Taquin(String titre){super(titre);nbLignesTaquin = 5;nbColonnesTaquin = 5;setBounds(0,0,largeurFenetre,hauteurFenetre);int x_0 = (largeurFenetre - Grille.getLargeurColonne()*

nbColonnesTaquin)/2;int y_0 = (hauteurFenetre - Grille.getHauteurLigne()*nbLignesTaquin

)/2;grille=new Grille(nbLignesTaquin,nbColonnesTaquin,x_0,y_0);click = new Click(grille);grille.addMouseListener(click);add(grille,"Center");setVisible(true);

}public static void main (String args []){

new Taquin("Jeu de Taquin");}

}

2.2 Semaine 4 : applications - modifications de l’interface gra-phique du labyrinthe

Pour cette application, le code initial est le code qui vous a été fourni au début du projet, dans :/net/Bibliotheque/AP3/projet/

Vous trouverez également des démos (binaires) de ce qui est attendu, dans :/net/Bibliotheque/AP3/TD02/

1. Modifier le moteur graphique pour que le déplacement du héro soit fluide (i.e. pixel par pixel), bien que ledéplacement soit toujours case par case ;

2. Ajouter à l’application la possibilité de se déplacer aussi en cliquant sur un composant graphique (un com-posant par direction).

Page 32: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

28 CHAPITRE 2. SEMAINES 3 & 4 : INTERFACES GRAPHIQUES EN SWING

Page 33: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

Chapitre 3

Semaines 5 & 6 : exceptions, collections

L’objectif de cette partie est de présenter dans un premier temps la gestion des exceptions en Java : le méca-nisme des exceptions offre un moyen simple pour réagir à des événements qui risquent de survenir, comme parexemple, une erreur de lecture sur un fichier.

La seconde moitié du cours est dédiée à la riche librairie de Java pour manipuler des ensemble ou multi-ensembles d’objets : l’API des collections.

L’ensemble des fichiers de cette séance est disponible dans :/net/Bibliotheque/AP3/TD03/code/

Sommaire3.1 Semaine 5 : exceptions et collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

3.1.1 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293.1.2 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343.1.3 Exercice à rendre : tri des arcs d’un graphe . . . . . . . . . . . . . . . . . . . . . . . . 37

3.2 Semaine 6 : application - mode multi-personnages et exceptions ExceptionSortie . . . 37

3.1 Semaine 5 : exceptions et collections

3.1.1 Exceptions

3.1.1.1 Motivation

Soit la classe suivante décrivant une Ville :

public class Ville{private String nom;private int nbHabitants;

public Ville(String nom){this.nom = nom;

}public Ville(String nom,int nbHabitants){

this(nom);setNbHabitants(nbHabitants);

}public final void setNbHabitants(int nbHabitants){

29

Page 34: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

30 CHAPITRE 3. SEMAINES 5 & 6 : EXCEPTIONS, COLLECTIONS

if(nbHabitants <= 0)erreur("nombre d’habitants doit etre > 0");

this.nbHabitants=nbHabitants;}protected void erreur(String message){

System.out.println("ERREUR : classe : " + getClass().getName() + ": " + message);

System.exit(1);}

...public static void main (String args []){Ville v = new Ville("Shanghai",-1);

}}

1. Que se passe t-il lors de l’exécution ?

Lors d’un appel à setHabitants avec un paramètre incorrect :– la méthode erreur est appelée,– un message décrivant l’erreur est affiché,– le programme s’interrompt (brutalement).Dans le cas présent, l’arrêt brutal n’est pas justifié ; nous aimerions refaire un appel avec un paramètre correct

et continuer l’exécution du programme. Mais nous n’avons pas envie de surcharger le code avec des instructionsrendant les algorithmes illisibles. Vous avez certainement constaté la multiplication de clauses if(...)... afinde gérer les cas limites qui peuvent intervenir dans vos programmes : division par zéro,...

Important : Le plus souvent, la méthode constatant l’erreur n’est pas habilitée à prendre la meilleure décisionpour la traiter :

– je redemande une saisie ?– je m’arrête ?– j’affiche un message et je continue (vaille que vaille) ?D’où le besoin d’un mécanisme de gestion des erreurs : besoin d’un moyen de détection, besoin d’un moyen

de gestion, besoin d’un moyen de reprise.

Revenons à notre exemple. Ajoutons le code suivant :

public class NbHabException extends Exception{private int nbErr;

public NbHabException(int nbErr){this.nbErr = nbErr;

}public String toString(){

return "Nb habitants éerron : " + nbErr ;}

}

public class Ville{...

public final void setNbHabitants (int nbHabitants) throwsNbHabException{if(nbHabitants <= 0)

throw new NbHabException(nbHabitants);this.nbHabitants=nbHabitants;

}

Page 35: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

3.1. SEMAINE 5 : EXCEPTIONS ET COLLECTIONS 31

Notez la création de la classe NbHabException spécialisant la classe Exception et la modification de laméthode setNbHabitants.

Et cela change quoi ?– On détecte l’erreur.– On prévient l’environnement.La méthode ayant détectée l’erreur ne la gère pas : il y a séparation entre détection et gestion. Plus précisé-

ment, que se passe t’il lors de l’exécution de la ligne suivante ?

throw new NbHabException(nbHabitants);

i. L’argument est évalué.

ii. Un objet de la classe NbHabException est instancié.

iii. L’instruction throw lève une exception.

iv. La méthode courante (setHabitants) est stoppée.

v. Le gestionnaire d’exceptions prend la main : setHabitants a levé une exception. Il enlève de la piled’exécution l’environnement associé à la méthode setHabitants.

vi. Il rend (éventuellement) la main à la méthode ayant appelé setHabitants. En fait, le gestionnaire d’ex-ceptions va remonter la pile d’appels jusqu’à trouver une méthode capable de gérer l’exception.

public final void setNbHabitants (int nbHabitants) throws NbHabException{

if(nbHabitants <= 0)throw new NbHabException(nbHabitants);

...

La signature stipule que la méthode est susceptible de lever une exception du type NbHabException et elleprécise au compilateur que toute méthode appelant setHabitants devra se préoccuper de cette exception : soiten la traitant, soit en la propageant.

2. Compiler et observer.

On observe une erreur lors de la création de l’instance :

public Ville(String nom,int nbHabitants) {this(nom);setNbHabitants(nbHabitants);

}

"NbHabException must be caught or it must be declared in the throws clause of this method"

Erreur : Le constructeur Ville appelant setHabitants ne gère pas l’exception NbHabExceptionsusceptible d’être levée. Le constructeur doit soit traiter l’exception, soit la propager.

Modifions l’entête du constructeur Ville afin de propager l’exception :

public Ville(String nom,int nbHabitants) throws NbHabException {this(nom);setNbHabitants(nbHabitants);

}

OK... nous propageons l’exception mais qui la traite et comment ?

Cela se fait via le bloc d’instruction try... catch... finally :

Page 36: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

32 CHAPITRE 3. SEMAINES 5 & 6 : EXCEPTIONS, COLLECTIONS

public final class VilleApp{public static void main (String args []){

try { // Capture de l’exceptionVille v = new Ville("Shanghai",-1);

}catch(NbHabException e){

// l’exception est capturee, on la traiteSystem.out.println(e);

}finally{

// bloc optionnel, execute quoiqu’il advienneSystem.out.println("finally");

}}

}

Le déroulement étape par étape est donc le suivant :

i. appel du constructeur

ii. appel de setNbHabitants(-1), qui lève une exception

iii. dépilement de l’environnement de setNbHabitants et propagation de l’exception au constructeur

iv. le constructeur ne capturant pas l’exception, son environnement est dépilé (aucun objet instancié) ; l’excep-tion est propagée à la méthode appelante (ici main)

v. la clause catch de main capture l’exception et provoque l’exécution du bloc qui lui est associé.

3.1.1.2 Synthèse

– Une exception est un objet qui est instancié lors d’un incident : une exception est levée.– Le traitement du code de la méthode est interrompu et l’exception est propagée à travers la pile d’exécution

de méthode appelée en méthode appelante.– Si aucune méthode ne capture l’exception : celle-ci remonte l’ensemble de la pile d’exécution ; l’exécution

se termine avec une indication d’erreur.– La capture est effectuée avec les clauses try... catch.– La clause try définit un bloc d’instructions pour lequel on souhaite capturer les exceptions éventuellement

levées. Si plusieurs exceptions peuvent se produire, l’exécution du bloc est interrompue lorsque la premièreest levée. Le contrôle est alors passé à la clause catch.

– La clause catch définit l’exception à capturer, en référençant l’objet de cette exception par un paramètrepuis le bloc à exécuter en cas de capture.

3.1.1.3 Compléments

Toutes les exceptions héritent de la classe Throwable.

– Throwable()– Throwable(String) : la chaîne passée en paramètre sert à décrire l’incident– getMessage() : info– printStackTrace() : exception + état de la pile d’exécution

Throwable possêde deux classes filles Error et Exception :

– Error : erreurs graves de la machine virtuelle (état instable, récursivité infinie, classe en chargement nontrouvée,...).

– Exception : ensemble des erreurs pouvant être gérées par le programmeur (RunTimeExeption(NullPointerException, IndexOutOfBoundsException, ArithmeticException),IOException, ...).

Page 37: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

3.1. SEMAINE 5 : EXCEPTIONS ET COLLECTIONS 33

Java n’oblige la déclaration explicite d’une levée d’exception que pour les exceptions dites contrôlées (enanglais checked) (... throws NbHabException).

– unchecked : RunTimeException,... (toutes les exceptions définies dans l’API), Error– checked : les autres (celles du programmeur)

3.1.1.4 Exercice : ThrowTest

1. Écrire la classe ThrowTest : celle-ci contient une méthode main. La méthode main récupère l’argumentpassé en ligne de commande au moyen de :

i=Integer.parseInt(argv[0])

2. La méthode main capture les exceptions eventuelles ArrayIndexOutOfBoundsException etNumberFormatException. Si une de ces exceptions est levée, alors affichez un message et terminezl’exécution.

Un peu d’aide ?

public class ThrowTest {public static void main (String argv[]){

int i;try{

i = Integer.parseInt(argv[0]);}catch(ArrayIndexOutOfBoundsException e){// argv est vide

System.out.println("Vous devez saisir un argument");return;

}catch(NumberFormatException e){// l’argument n’est pas un entier

System.out.println("L’argument specifie doit etre un entier");return;

}}

}

3. Définissez deux exceptions :MyException étendant ExceptionMyOtherException étendant Exception

Par exemple :

class MyException extends Exception{public MyException(){

super();}public MyException(String s){

super(s);}

}

4. Dans la classe ThrowTest, ajouter les méthodes suivantes :– Méthode b(int i) :

si l’entier i vaut 0, alors la méthode c lève une exception du type MyException ;si l’entier i vaut 1, alors la méthode c lève une exception du type MyOtherException ;pour toute autre valeur de i le message “input ok” est affiché.

Page 38: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

34 CHAPITRE 3. SEMAINES 5 & 6 : EXCEPTIONS, COLLECTIONS

– Méthode a(int i) : appelle b(i) et capture toutes les exceptions.– La méthode main appelle a(i).Un peu d’aide ?

public static void a (int i){try{

b(i);}catch(Exception e){

if (e instanceof MyOtherException)System.out.println("MyOtherException");

elseSystem.out.println("MyException");

System.out.println(e);}

}

public static void b (int i) throws MyException, MyOtherException{switch(i){

case 0: throw new MyException("input 0 -> MyException");case 1: throw new MyOtherException("input 1 ->

MyOtherException");default:System.out.println("input ok : " + i);

}}

5. Écrire la trace du programme en fonction des valeurs de i.6. Observer les mécanismes d’exceptions suivant les valeurs de i.

3.1.2 Collections

Nous allons maintenant aborder l’API des Collections en Java.

3.1.2.1 L’interface Collection

L’interface Collection est une des principales interfaces de Java. Elle sert pour le stockage et le parcoursd’un ensemble d’objets, pas nécessairement de même type.

3.1.2.2 Prototype

Cette interface possède deux méthodes essentielles :

boolean add(Object obj)Iterator iterator()

La méthode add ajoute un objet dans la collection. Elle renvoie true si l’ajout de l’objet a effectivementmodifié la collection, false sinon.

La méthode iterator renvoie un objet qui implémente l’interface Iterator.

Cette interface possède trois méthodes principales :

Object next()boolean hasNext()void remove()

Page 39: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

3.1. SEMAINE 5 : EXCEPTIONS ET COLLECTIONS 35

En appelant plusieurs fois la méthode next, vous pouvez parcourir tous les éléments de la collec-tion un par un. Lorsque la fin de la collection est atteinte, la méthode next déclenche une exceptionNoSuchElementException 1. Enfin, la méthode remove supprime l’élément renvoyé par le dernier appel ànext.

Iterator i = c.iterator();while (i.hasNext()){

Object o = i.next();}

L’interface Collection déclare aussi ces méthodes, dont les prototypes sont suffisamment explicites :

int size()boolean isEmpty()boolean containsObject( Object )boolean containsAll( Collection )boolean equals( Object )boolean addAll( Collection )boolean remove( Object )boolean removeAll( Collection )void clear()boolean retainAll( Collection )Object[] toArray()

La classe AbstractCollection définit les méthodes fondamentales (add, size et Iterator) commeabstraites et implémente toutes les autres. Une classe de collection concrète peut donc se limiter à l’implémentationdes méthodes fondamentales.

3.1.2.3 Les listes doublement chaînées

La classe LinkedList est l’implémentation Java des listes doublement chaînées. Elle implémente l’interfaceCollection.

– Avantages : suppression, ajout d’un élément rapide ;– Inconvénients : récupération d’un élément nécessite le parcours des éléments qui le "précède".

La méthode add fournie ajoute un élément en fin de liste.

Pour ajouter un élément au sein de la liste, il faut utiliser un objet ListIterator (une interface héritant del’interface Iteratoir) qui permet l’insertion d’un élément à la position courante, via sa méthode add .La classeListIterator ajoute également 2 méhtodes previous and hasPrevious qui permettent le parcours de laliste à rebours.

Exemple (ajout de la chaine "bob", en deuxième position)

LinkedList ll = new LinkedList();...ListIteratoi li = ll.listIterator();li.next();li.add("Bob");

La classe ListIterator possède aussi une méthode set qui permet de substituer un objet à l’élémentcourant. La classe LinkedList dispose d’une méthode get( int i ) retournant l’élément d’indice i, maissi vous l’utilisez, c’est que vos données ne devraient pas être stockées sous forme d’une liste chaînée ! ! !

1. Les exceptions seront étudiées dans une prochaine séance

Page 40: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

36 CHAPITRE 3. SEMAINES 5 & 6 : EXCEPTIONS, COLLECTIONS

3.1.2.4 les vecteurs ou tableaux dynamiques

La classe ArrayList encapsule un tableau classique Object[] dans un tableau dynamique. Elle implé-mente l’interface List. Les méthodes get et set sont donc disponibles pour accéder directement aux élémentsd’un ArrayList. Il est préférable d’utiliser un ArrayList à chaque fois que vous n’avez besoin d’accéder àvotre tableau qu’à partir d’un seul processus, car les méthodes de la classe Vector sont moins performantes, carelles sont toutes synchronisées (i.e. elles sont adaptées à des accès concurrents par plusieurs processus).

3.1.2.5 Les tables de hachage

Les listes chaînées et les tableaux vous permettent de spécifier l’ordre (linéaire) dans lequel vous organisezvos éléments. Si l’ordre n’a pas d’importance, il existe des structures de données qui vous permettent de retrouverun élément beaucoup plus rapidement.

Une structure de données classique pour retrouver simplement un élément est la table de hachage. Une tablede hachage calcule un nombre entier, appelé code de hachage, pour chacun des éléments. Elle est constituée d’untableau de listes chaînées.

Un élément est stocké dans la liste correspondant à son code de hachage modulo le nombre de listes. Ainsipour retrouver un élément, il suffit de réduire son code de hachage modulo le nombre de listes, et parcourir la listeà sa recherche.

Les tables de hachage peuvent servir à implémenter plusieurs structures de données. Par exemple, la classeHashSet modélise un ensemble. Un ensemble correspond simplement à une collection d’éléments ne figurantqu’une seule fois chacun dans la collection. La méthode add n’ ajoute un élément que s’il n’est pas déjà présent.

L’insertion des éléments dans un HashSet se base sur la méthode hashCode. Celle qui est fournie pourtout objet n’est pas très utile car elle repose uniquement sur l’adresse mémoire de l’objet. Il faut donc la redéfinirpour qu’elle ne dépende que du contenu de l’objet. Pensez dans ce cas également à redéfinir equals !

3.1.2.6 les collections ordonnées

La classe TreeSet repose également sur une table de hachage et permet de stocker des ensembles ordonnés,moyennant une petite pénalité.

La comparaison entre deux éléments est faite via la méthode compareTo de l’interface Comparable.

3.1.2.7 Les vues

Les méthodes des collections ne sont pas synchronisées, ce qui signifie que pour améliorer les performances, iln’y pas pas de protection gérant les accès concurrents de la part des processus. Il est possible néanmoins d’obtenirdes vues synchronisées, en faisant appel à certaines méthodes de la classe Collections, comme dans l’exempleci-dessous :

HashMap hm = new HashMap();Map map = Collections.synchronizedMap(hm);

Vous pouvez également obtenir une collection en lecture seule (vue non modifiable), comme dans cet exemple

List l = new LinkedList();List l2 = new Collections.unmodifiableList(l);

Il est aussi possible de travailler directement avec un sous-ensemble (vue restreinte) : ainsi le code

List groupe2 = etudiants.subList(10,20);

définit le groupe 2 comme les éléments d’indice 10 à 19.

Page 41: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

3.2. SEMAINE 6 : APPLICATION - MODE MULTI-PERSONNAGES ET EXCEPTIONS EXCEPTIONSORTIE 37

3.1.2.8 Opérations de masse

Une opération de masse permet de manipuler directement un ensemble d’éléments d’une liste. Par exemplepour calculer l’intersection entre deux ensembles a et b, vous pouvez utiliser :

a.retainAll(b);

Autre exemple, pour ajouter les 10 premiers éléments d’une liste b dans une liste a :

a.addAll( b.subList( 0,10 ) );

3.1.2.9 Algorithmes

La méthode Collections.sort permet de trier une collection ordonnée (interface List). Par défaut, elleutilise comme critère de tri l’implémentation de compare de la collection à trier. Il est possible de lui préciser unautre critère de tri directement : par exemple

Collections.sort( cadres, new Comparator(){public int compare(Object a, Object b){

double differenceSalaires = (Salarie) a.getSalaire() - (Salarie) b.getSalaire();

if (differenceSalaires < 0 ) return -1;if (differenceSalaires > 0 ) return 1;return 0;}

});

trie une liste cadres d’objets de type Salarie en fonction de leur salaire.

Ceci s’applique aussi aux méthodes génériques de– calcul d’un plus grand élément : Collections.max ;– recherche dichotomique d’un élément : Collections.binarySearch (à n’appliquer à des collec-

tions triées ;-))

3.1.3 Exercice à rendre : tri des arcs d’un graphe

Ecrire une méthode tri() de la classe Graphe qui effectue un tri de ses arcs selon l’ordre suivant : un arci j est inférieur ou égal à un arc i′ j′ si et seulement si i≤ i′ et j ≤ j′. Prévoir dans la méthode main une exécutionqui montre sur un exemple le bon fonctionnement de votre méthode, en affichant les arcs d’un graphe avant etaprès le tri.

3.2 Semaine 6 : application - mode multi-personnages et excep-tions ExceptionSortie

Exceptions On désire gérer la sortie du personnage d’un labyrinthe par le biais d’une exception : les étapesci-après vous donnent un fil conducteur pour le réaliser.

1. extraire l’archive AP3TD03Applications.jar qui contient le code de départ ;

2. écrire une exception ExceptionSortie dans le paquet labyrinthe, dont la méthode toStringrenvoie "ExceptionSortie: alerte - un intrus est sorti du labyrinthe" ;

3. modifier l’interface Salle pour que la méthode recevoir puisse lever une exceptionExceptionSortie : ainsi, lors d’un déplacement d’un personnage vers la sortie, cette dernièredéclenchera l’exception ;

4. modifier la méthode main pour capturer cette exception et la traiter ;

Page 42: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

38 CHAPITRE 3. SEMAINES 5 & 6 : EXCEPTIONS, COLLECTIONS

5. supprimer la méthode sortir de l’interface Labyrinthe car elle n’est plus utile ;

6. modifier la classe SalleCarree pour qu’elle lève une exception ExceptionSortie à bon escient :pour ce faire, une salle carrée a besoin de pouvoir connaître la sortie du labyrinthe ...

7. le mécanisme devrait être maintenant pleinement opérationnel : dans la méthode main, modifier le trai-tement effectué lors de la capture d’une exception ExceptionSortie pour que le héros en sortant dulabyrinthe arrive dans un nouveau labyrinthe : quelle chance !

Un peu d’aide pour la dernière question ?

public class LabyrintheApp {

static LabyrintheGrille labyrinthe;static Personnage bob;static Dessin dessin;static JFrame frame;static PanneauDirections directions;

public static void init(String laby) {// modelelabyrinthe = new LabyrintheGrilleDefaut();labyrinthe.creerLabyrinthe(laby);bob = new PersonnageClavier();((PersonnageDefaut) bob).peutSeDeplacer=true;labyrinthe.entrer(bob);dessin = new Dessin(labyrinthe,bob);directions = new PanneauDirections((PersonnageClavier)bob);// positionnement graphique initial de bobSalle s = bob.getPosition();dessin.xpix = ((SalleCarree) s).getColonne()*dessin.unite;dessin.ypix = ((SalleCarree) s).getLigne()*dessin.unite;// vueJFrame.setDefaultLookAndFeelDecorated(true);frame = new JFrame("Labyrinthe "+laby);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// contenu de la fenetredessin.setFocusable(true);dessin.requestFocus();frame.setLayout(new FlowLayout());frame.add(dessin); // vue principale (vue 2D du labyrinthe)frame.add(directions); // panneau des directionsframe.pack();frame.setVisible(true);

}

public static void main (String[] args){if (args.length==0)

init("labys/level3.txt");else init(args[0]);

while(true){Collection<Salle> sallesAccessibles = labyrinthe.

sallesAccessibles(bob);Salle destination = bob.faitSonChoix(sallesAccessibles); //

on demande au heros de faire son choix de salletry {

Page 43: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

3.2. SEMAINE 6 : APPLICATION - MODE MULTI-PERSONNAGES ET EXCEPTIONS EXCEPTIONSORTIE 39

if (destination!=bob.getPosition()) destination.recevoir(bob); // deplacement

}catch(ExceptionSortie es) {

// le hero est sorti - faire le traitementapproprie: ici, charger un nouveau labyrinthe

System.out.println(es);frame.dispose();init("labys/level7.txt");

}//rafraichissement de la vuedessin.repaint();directions.repaint();

}}

Mode multi-personnages Notre héros peut maintenant parcourir moult labyrinthes, mais il se sent un peuseul. Nous allons maintenant rajouter des monstres, qui se déplaceront de manière aléatoire, i.e. pour se dépla-cer leur méthode faitSonChoix renverra une salle au hasard parmi les salles accessibles. Notre applicationcontiendra donc une collection de personnages, l’un d’entre eux étant le héros, les autres étant des monstres. C’estune occasion rêvée d’exploiter le polymorphisme ... Un monstre ne pourra pas sortir d’un labyrinthe.

1. modifier la classe LabyrintheApp pour que celle-ci possède une collection de personnages : dans unpremier temps, cette collection ne contiendra que le personnage du héros. Adapter la boucle principale pourqu’elle déplace tous les personnages.

2. rajouter une méthode public void paint(Graphics g, int x, int y, int unite)dans l’interfacePersonnage : ainsi chaque personnage prendra en charge son propre dessin et les monstrespourront décider de leur apparence.

3. mettre en place le dessin du héros dans la classe PersonnageClavier et adapter la classe Dessin enfonction.

4. rajouter la collection de personnages comme attribut de la classe Dessin et adapter son code : vive lepolymorphisme !

5. créer une classe Monstre qui se déplace de manière aléatoire ; chaque monstre étant dessiné sous la formed’un disque. Un peu d’aide ?

public class Monstre extends PersonnageDefaut{static Random generator = new Random();Color couleur;

public Monstre() {couleur = new Color(generator.nextInt(255),generator.

nextInt(255),generator.nextInt(255));peutSeDeplacer=true;

}

public Salle faitSonChoix(Collection<Salle> sallesAccessibles){// choix éalatoirereturn (Salle)(sallesAccessibles.toArray())[generator.

nextInt(sallesAccessibles.size())];}

public void paint(Graphics g, int x, int y, int unite){

Page 44: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

40 CHAPITRE 3. SEMAINES 5 & 6 : EXCEPTIONS, COLLECTIONS

g.setColor(couleur);g.fillOval(x, y, unite,unite);

}}

6. créer une bonne dizaine de monstres et les placer de manière aléatoire dans le labyrinthe. Un peu d’aide ?

// autres personnagesRandom generateur = new Random();for (int i=0; i<10; i++) {

Monstre m = new Monstre();personnages.add(m);int h,l;Salle sa = null;do{ h = generateur.nextInt(labyrinthe.getHauteur());

l = generateur.nextInt(labyrinthe.getLargeur());sa = ((LabyrintheGrilleDefaut) labyrinthe).salles[h][l];

} while ( sa==null);m.setPosition(sa);

}

7. déplacer les coordonnées graphiques xpix et ypix de PersonnageClavier àPersonnageDefaut, de sorte que les monstres soient gérés au pixel près aussi : adapter le codede Dessin en fonction.

8. adapter la méthode recevoir de SalleCarree, pour que l’exception de sortie de labyrinthe ne soitlevée que pour le héros.

9. bien remuer et servir chaud.

Page 45: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

Chapitre 4

Semaines 7 & 8 : JUnit, sérialisation, RMI

4.1 Semaine 7 : cours

4.1.1 JUnit : tests unitaires

ObjectifsJUnit est une librairie dédié au test d’une application Java.

Avec JUnit, on peut créer un ensemble de classes dans le même projet, pour tester les classes propres au projet.

JUnit sert donc à séparer le code dédié aux tests du code de l’application.

Un développeur peut définir un ensemble de contraintes que doit satisfaire une classe. Si un autre développeurchange le code de la classe, il n’a besoin que de quelques clics pour s’assurer que la classe est toujours valide.

ExempleJUnit procure les méthodes de test suivantes : assertEquals(a,b), assertFalse(a), assertNotNull(a), assert-

NotSame(a,b), assertNull(a), assertSame(a,b), , assertTrue(a).Exemple de classe de test

import junit.framework.TestCase;public class TestFacture extends TestCase {

public void testAjoutArticles(){Facture maFacture = new Facture();maFacture.add(new Article("a"),3,150);maFacture.add(new Article("b"),1,50);assertNotNull("La facture ne devrait pas etre nulle",

maFacture);assertEquals("Le total de la facture est mal calcule",

3*150+50,maFacture.getTotal(), 0.01);}

}

TestFacture

public class Facture {public void add( Article a, int quantite, double prix){}public double getTotal(){return 0;}

}

41

Page 46: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

42 CHAPITRE 4. SEMAINES 7 & 8 : JUNIT, SÉRIALISATION, RMI

Article

public class Article {public Article( String libelle ){}

}

Le test assertEquals("Le total de la facture est mal calculé",3*150+50,maFacture.getTotal(),0.01) nepasse pas.

A vous de jouer Tester ce code dans Eclipse, puis faire votre propre test unitaire pour vérifier qu’un unijambistea bien une seule jambe.

4.1.2 Sérialisation : objets persistants

4.1.2.1 L’interface Serializable

Sérialisation Procédé permettant de mettre un objet sous une forme à partir de laquelle il pourra être recons-titué à l’identique.

Ceci permet de sauvegarder des objets sur disque, ou bien de les transmettre via le réseau.

Le format utilisé est indépendant du système d’exploitation.

La sérialisation utilise les classes ObjectOutputStream et ObjectInputStream et l’interface Serializable.

Cette interface ne définit aucune méthode. Tout objet qui doit être sérialisé doit implémenter cette interface. Sil’on tente de sérialiser un objet qui n’implémente pas l’interface Serializable, une exception NotSerializableEx-ception est levée.

4.1.2.2 La classe ObjectOutputStream

ObjectOutputStream Cette classe permet d’obtenir un flux en sortie pour écrire/envoyer des objets sériali-sables.

FileOutputStream fichier = new FileOutputStream("equipage.ser");ObjectOutputStream oos = new ObjectOutputStream(fichier);oos.writeObject(e);oos.flush();oos.close();

Toutes les variables de la classe à sérialiser, doivent-elles même être sérialisable. Par exemple, si l’objetcontient une collection d’éléments, chaque élément de la collection doit être sérialisable.

4.1.2.3 Exemple

Exemple Ainsi dans le code suivant, les objets Equipage et ExtraTerrestre doivent être sérialisables :

Equipage e = new Equipage();e.add( new ExtraTerrestre(2));e.add( new ExtraTerrestre(3));e.add( new ExtraTerrestre(2));System.out.println(e);try {

FileOutputStream fichier = new FileOutputStream("equipage.ser");ObjectOutputStream oos = new ObjectOutputStream(fichier);oos.writeObject(e);oos.flush();oos.close();} catch ...

Page 47: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

4.1. SEMAINE 7 : COURS 43

Sauvegarder ainsi un Equipage.

4.1.2.4 La classe ObjectInputStream

ObjectInputStream Cette classe permet d’obtenir un flux en entrée pour lire/recevoir des objets sérialisés.

try {FileInputStream fichier = new FileInputStream("equipage.ser");ObjectInputStream ois = new ObjectInputStream(fichier);Equipage e = (Equipage) ois.readObject();System.out.println(e);ois.close();

} ...

Quitter Eclipse, le relancer et utiliser ce code pour récupérer votre instance d’Equipage précédemment sauve-gardée.

4.1.3 RMI

4.1.3.1 RMI

Remote Methode Interface

RMI Permet de créer et manipuler des objets distants. Un objet distant est un objet qui implément une interfacedistante, sachant qu’une interface distante est une interface héritant de l’interface Remote, et dont toutes lesméthodes sont susceptibles de lever une exception RemoteException.

Les méthodes d’un objet distant doivent retourner un objet sérialisable (y compris les types de base).

Exemple

public interface RemoteInterface extends Remote{String bzzz() throws RemoteException;Equipage getEquipage() throws RemoteException;

}

4.1.3.2 Instanciation de l’objet distant

L’objet distant doit naturellement implémenter l’interface que nous avons définie.

Instanciation de l’objet distant Avec la méthode exportObject, on obtient une référence susceptible d’êtreaccessible à distance. La classe Registry permet d’accéder au catalogue d’objets distant (cf commande rmiregistryci-apres), et la méthode bind donne un nom l’instance de l’objet distant (identifiant).

Le catalogue d’objets distant doit être lancé au préalable avec la commande rmiregistry num_port . Uneméthode alternative consiste à instancier directement le magasin avec :

java.rmi.registry.LocateRegistry.createRegistry(port);

En java 1.4, il était également nécessaire d’utiliser la commande rmic sur le binaire côté serveur pour générerune copie "utilisable" à distance : à partir de la version 1.5, ce n’est plus nécessaire ... en théorie !

Page 48: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

44 CHAPITRE 4. SEMAINES 7 & 8 : JUNIT, SÉRIALISATION, RMI

4.1.3.3 Exemple

La partie main ci-dessous contient le code pour créer une instance de l’objet et le mettre à disposition :

public class ServeurRMI implements RemoteInterface{public ServeurRMI(){}public String bzzz(){return "bzzzzzzzzzzzzzzzzzzzzzzzz";}public Equipage getEquipage(){

Equipage e = new Equipage(); e.add( new ExtraTerrestre(2));e.add( new ExtraTerrestre(3)); e.add( new ExtraTerrestre(2));return e;

}public static void main(String[] args) {

int port = 12345; ServeurRMI sr = new ServeurRMI();try{

RemoteInterface ri = (RemoteInterface) UnicastRemoteObject.exportObject(sr);

LocateRegistry.createRegistry(port);Registry r = LocateRegistry.getRegistry(port);r.bind("monObjetDistant",ri);System.out.println("serveur d’objets distant pret");

}catch (Exception e){System.out.println(e);}}}

4.1.3.4 Coté client

Côté client Coté client, il suffit simplement de demander un accès au catalogue distant puis obtenir une réfé-rence sur l’objet distant avec la méthode lookup en lui précisant le nom de l’objet cible.

public class ClientRMI {

public static void main(String[] args) {String serveur="127.0.0.1"; int port = 12345;try{

Registry r = LocateRegistry.getRegistry(serveur, port);RemoteInterface ri = (RemoteInterface) r.lookup("

monObjetDistant");System.out.println(ri.bzzz());System.out.println(ri.getEquipage());

}catch (Exception e){

System.out.println(e);}

}}

4.1.3.5 Gestionnaire de sécurité

Il est possible de mettre en place un gestionnaire de sécurité sur le serveur et/ou le client, notamment pourpermettre le chargement dynamique des classes :

System.setSecurityManager(new RMISecurityManager());

Tester le client précédent, et observer le transfert (sérialisation) des membres de l’équipage.

Page 49: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

4.2. SEMAINE 8 : APPLICATION FINALE 45

4.2 Semaine 8 : application finale

Page 50: AP3 - programmation orientée objet en Javathomas.morsellino.fr/teaching/[2012-2013]_S3-Prog-Objet/support.pdf · Chapitre 1 Semaines 1 & 2 : héritage, polymorphisme, transtypage,

46 CHAPITRE 4. SEMAINES 7 & 8 : JUNIT, SÉRIALISATION, RMI