La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Présentation du cours de Conception et de Programmation Orientée Objet - Java Philippe Canalda Master 1 PSM – Montbéliard – Conception et Programmation.

Présentations similaires


Présentation au sujet: "Présentation du cours de Conception et de Programmation Orientée Objet - Java Philippe Canalda Master 1 PSM – Montbéliard – Conception et Programmation."— Transcription de la présentation:

1 Présentation du cours de Conception et de Programmation Orientée Objet - Java
Philippe Canalda Master 1 PSM – Montbéliard – Conception et Programmation Avancée MultiMédia UFR STGI / LiFC EA 4269 Octobre 2008

2 En préambule Organisation En groupe de 4 au sein de votre groupe de TP
Nomination du 1er groupe prenant les notes dans ce cours et chargé de délivrer À la fin de la journée, un cr À la fin de la semaine une version corrigée/étendue matériel utilisé : tous les matériaux de ce cours : src présentation, codes src, corrections d’exercices, etc. intégration du travail d’autrui

3 1ère intervention CM : prises de notes : X + Y
Organisation de l’enseignement 1ère illustration d’une application intégrant une caméra, un mur d’écran, un service (architecture serveur ou C/S) qui détermine les groupes d’étudiants de 4 éléments (complétion à moins) au sein des sous-groupes A, B et C Affichage des visages à inter changer afin de placer le sous-groupe formé aux places de la salle où se trouvent assis tous les sous-groupes déjà formés. Déroulement de l’algorithme de tri par insertion et constitution des groupes d’étudiant Présentation <orale> des applications multimédia et les challenges des nouveaux services : prise en compte des handicaps, des nouveaux usages (mobilité intérieur ou extérieur), des réseaux de capteurs Présentation du projet, contraintes, fonctionnalités, méthode, diagramme de GANT

4 Prise de notes de X = Delphine Tirole Y = Mikaël Geljic

5 1ère intervention TD 1er jet cdc du projet inspiré de FrozenBubble
Présentation succinct de tous les projets au sein du TD 1er jet conception avec exposé des RI (Représentations Informatiques) nécessaires, 1ères fonctionnalités

6 1ère intervention TP : prise de notes
TP1 X' + Y' TP2 S. X''+Y'' Conception et réalisation des principales fonctions de votre projet (au – 2 fonctionnalités)‏ Calcule des boules qui sont en contact d’une boule initiale

7 Plan Présentation de ce qui vous attend Bibliographie
Programmation objet Le langage Java Algorithmique 1 (rappel) et 2 ...

8 Plan ... Notions d’UML : les 7 (sur 12) diagrammes de conception et de développement Les classes fondamentales La programmation concurrente Les flots Les composants awt de java Introduction à Swing Réseau JDBC Java Xml

9 Bibliographie Livre de référence Hortsmann et Cornell, Au coeur de Java 1 et 2, CampusPress. Gilles Roussel, Etienne Duris, Java et Internet : concepts et programmation, Vuibert 2002 Transparents de Marie-Pierre Béal, et Jean Berstel.

10 Bibliographie Autres ouvrages sur Java
Patrick Niemeyer, Joshua Peck (Traduction de Eric Dumas), Java par la Pratique, O'Reilly International Thomson, 1996. Matthew Robinson and Pavel Vorobiev, Swing, Manning Publications Co., december 1999. Sur les design Pattern Erich Gamma, Richard Helm, Ralph Johnsons, John Vlissides, Design Patterns, Addison-Wesley, Traduction française chez Vuibert (1999).

11 Bibliographie Sur l’UML
Michael Blaha & James Rumbaugh, Modélisation et Conception orientées objet avec UML2, 2ème édition, Pearson Education,2005. Craig Larman, UML2 et les Design Patterns, 3ème édition, Pearson Education, 2005. Martin Fowler, UML 2.0, Campus Press, 2004.

12 Bibliographie Site Web : http://java.developpez.com/
: Site officiel Java (JDK et doc.)‏ : Info sur Java applications, applets, packages, ... : idem : Java pour linux ...

13 Travail demandé Contrôle de Connaissances
Sur 6 semaines : Un projet inspiré de FrozenBubble En TP, puis à la maison Une participation/évaluation prises de notes En CM TD Et TP L’examen final de 1ère et de 2ème session

14 1- Programmation objet 1. Styles de programmation
2. Avantages du style objet 3. Un exemple 4. Héritage et composition 5. Exemple : disques et anneaux

15 1.1 Styles de programmation
Style applicatif Fondé sur l’évaluation d’expressions, où le résultat ne dépend que de la valeur des arguments (et non de l’état de la mémoire) Donne des programmes courts faciles à comprendre Usage intensif de la récursivité Langage typique Lisp, Caml

16 1.1 Styles de programmation
Style impératif Fondé sur l’exécution d ’instructions modifiant l ’état de la mémoire Utilise une structure de contrôle et des structures de données Usage intensif de l ’itération Langage typique Ada, C, Pascal, Fortran, Cobol

17 1.1 Styles de programmation
Style objet Un programme est vu comme une communauté de composants autonomes (objets) disposant de ses ressources et de ses moyens d’interaction Utilise des classes pour décrire les structures et leur comportement Usage intensif de l’échange de messages (métaphore)‏ Langage typique Simula, Smalltalk, C++, Java, Ocaml

18 1.2 Avantages du style objet
Facilite la programmation modulaire La conception par classe conduit à des composants réutilisables Un composant offre des services et en utilise d ’autres Il « expose » ses services à travers une interface Il cache les détails d ’implémentations (encapsulation ou data-hiding)‏ Tout ceci le rend ré-u-ti-li-sa-ble

19 1.2 Avantages du style objet
Facilite l ’abstraction L’abstraction sépare la définition de son implémentation L ’abstraction extrait un modèle commun à plusieurs composants Le modèle commun est partagé par le mécanisme d ’héritage L ’abstraction est véhiculée par une méthodologie qui conduit à la réutilisabilité

20 1.2 Avantages du style objet
Facilite la spécialisation La spécialisation traite des cas particuliers Le mécanisme de dérivation rend les cas particuliers transparents

21 1.3 Un exemple class Point { private int x; private int y;
public Point (int x, int y) { this.x = x; this.y = y; } public int getX() { return x; // équivalent à ‘ return this.x ’ public int getY() { return y; public int setX(int x) { return this.x = x; ...

22 1.3 Un exemple class Point { private int x; private int y;
public Point (int x, int y) { … } public int getX() { … } public int getY() { … } public int setX(int x) { … } public int setY(int y) { return this.y = y; } public void deplace(int dx, int dy){ this.x += dx; this.y += dy; public String toString() { return (thix.x + «, » + this.y); ...

23 1.3 Un exemple class Point { private int x; private int y;
public Point (int x, int y) { … } public int getX() { … } public int getY() { … } public int setX(int x) { … } public int setY(int y) { … } public void deplace(int dx, int dy){ … } public String toString() { … } public static void main(String[] args) { Point a = new Point(3,5); // déclare l ’objet a et instancie ses a.setY(6); // a = (3, 6) coordonnées a.deplace(1,1) ; // a = (4,7)‏ System.out.println(a); }

24 1.4 Héritage et composition
Par la composition, une classe utilise un autre service Un composant est souvent un attribut de la classe utilisatrice L ’exécution de certaines tâches est déléguée au composant le plus apte Le composant a la responsabilité de la bonne exécution Facilite la séparation des tâches en modules spécialisés

25 1.5 Exemple : disques et anneaux
class Disque { protected Point centre ; // composition protected int rayon ; public Disque(int x, int y, int rayon) { this.centre=new Point(x,y) ; // identique à super(x,y)‏ this.rayon = rayon ; } public String toString() { return this.centre.toString() + «,  » + rayon ; public void deplace(int dx, int dy) { this.centre.deplace(dx, dy); // délégation

26 1.5 Exemple : disques et anneaux
class Anneau extends Disque { // dérivation private int rayonInterne ; // composition public Anneau(int x, int y, int rayon, int rayonInterne){ super(x,y,rayon) ; // identique à this.Disque(x,y)‏ this.rayonInterne = rayonInterne ; } public String toString() { return super.toString() + « ,  » + rayonInterne ;

27 Info(s) diverse(s)‏ Ici fin cours 1

28 2.1 Premier exemple Le fichier TestHelloWorld.java :
Class TestHelloWorld { public static void main(String[] args) { System.out.println(« Bonjour! »); } La compilation : javac TestHelloWorld.java crée le fichier : TestHelloWorld.class L ’exécution : java TestHelloWorld Donne le résultat : Bonjour ! Il est usuel de donner une initiale majuscule aux classes, et une initiale minuscule aux attributs et aux méthodes Le nom du fichier qui contient le code source est en général le nom de la classe suffixé par .java

29 2.1 Deuxième exemple import java.awt.Frame; import java.awt.Graphics;
import java.awt.Color; /** ******\ * Classe affichant une fenêtre de nom « Hello World » contenant « Bonjour » Canalda 1.0 \******* */ public class TestHelloWorld extends Frame { /** * Constructeur */ public TestHelloWorld() { super(« Hello World ! »); setSize(200,100); show(); }

30 2.1 Deuxième exemple public class TestHelloWorld extends Frame { …
/** Méthode de dessin de la fenêtre graphics contexte d ’affichage */ public void paint(Graphics graphics) { graphics.setColor(Color.black); graphics.drawString(« Bonjour », 65, 60); } /* Méthode principale args arguments de la ligne de commande public static void main(String[] args) { new TestHelloWorld();

31 2.1 Deuxième exemple Création d e la documentation html
javadoc TestHelloworld visualisation avec un navigateur, comme Netscape $ls TestHelloWorld.class TestHelloWorld.html HelloWorld.java Questions : Donnez la liste complète des fichiers créés, capturez la fenêtre du navigateur et affichez la documentation html du 2ème exemple traité

32 2.1 Créer une documentation HTML
Il s ’agit de créer une documentation et non d ’établir les spécifications des classes. @author : il peut y avoir plusieurs auteurs @see : pour créer un lien sur une autre documentation Java @param : pour indiquer les paramètres d ’une méthode @return : pour indiquer la valeur de retour d ’une fonction @exception : pour indiquer quelle exception est levée @version : pour indiquer le numéro de version du code @since : pour indiquer le numéro de version initiale @deprecated : indique une méthode ou membre qui ne devrait plus être utilisée. Crée un warning lors de la compilation. - exemple : /** Utiliser plutôt afficher #afficher()‏ */

33 2.1 Un exemple /** * Classe permettant de manipuler des matrices
Canalda Fino 1.0 */ public class Matrice { private int n; private int [][] m; /** Premier constructeur. Cree une matrice nulle de taille donnee en * parametre. * @param n un entier pour la taille * @see Matrice#Matrice(int, int)‏ ...

34 2.1 Un exemple public class Matrice { private int n;
private int [][] m; /** Premier constructeur. Cree une matrice nulle de taille donnee en * parametre. * @param n un entier pour la taille * @see Matrice#Matrice(int, int)‏ */ public Matrice(int n){ this.n=n; this.m=new int [n][n]; } /** Deuxieme constructeur. Cree une matrice dont la taille et le contenu * sont donnes en parametre. * @param x un entier pour le contenu de chaque case * @see Matrice#Matrice(int)‏ */ …

35 2.1 Un exemple public class Matrice { private int n;
private int [][] m; /** Deuxieme constructeur. Cree une matrice dont la taille et le contenu * sont donnes en parametre. * @param n un entier pour la taille * @param x un entier pour le contenu de chaque case * @see Matrice#Matrice(int)‏ */ public Matrice(int n, int x){ this.n=n; this.m=new int[n][n]; for(int i=0; i<n; i++)‏ for(int j=0; j<n; j++) this.m[i][j]=x; } …

36 info Fin 2ème cours prises de notes : TD – prises de notes
TP – prises de notes A B C

37 2.1 Un exemple public class Matrice { private int n;
private int [][] m; /** Methode de transposition de matrice */ public void transposer(){ for(int i=0; i<n; i++)‏ for(int j=i+1; j<n; j++) { int t=this.m[i][j]; this.m[i][j]=this.m[j][i]; this.m[j][i]=t; } /** Methode d’affichage d ’une matrice

38 2.1 Un exemple public class Matrice { private int n;
private int [][] m; /** Methode d ’affichage d ’une matrice */ public String toString(){ StringBuffer sb = new StringBuffer(); for(int i=0; i<n; i++)‏ for(int j=0; j<n; j++) { sb.append(m[i][j]); sb.append(«  »); } sb.append(«  \n»); return sb.toString(); /** Methode principale */

39 2.1 Un exemple public class Matrice { private int n;
private int [][] m; /** Methode principale * @param args arguments de la ligne de commande */ public static void main(String[] args){ Matrice a = new Matrice(3,12); System.out.print(a); Matrice b = new Matrice(3); System.out.print(b); } Question : Générez la documentation HTML et visualisez-la au moyen de votre navigateur préféré.

40 Cours 3

41 2.1 Fractales Principe : objets définis récursivement.
Exemple : la courbe du dragon de Heighway, qui est donnée par l ’applette suivante : import java.awt.*; import java.applet.*: public class Dragon extends Applet { public void paint(Graphics g) { g.setColor(Color.red); drawDragon(g,20,100,100,200,200); } private void drawDragon(Graphics g, int n, int x, int y, int z, int t) { int u,v; if (n==1)‏ g.drawLine(x, y, z, t); else { u = (x + z + t - y) / 2; v = (y + t - z + x) / 2 drawDragon(g, n-1, x, y, u, v); drawDragon(g, n-1, z, t, u, v);

42 2.1 Exécution d ’une applette
On crée un fichier DessinDragon.html contenant : <HTML> <HEAD> <TITLE> Courbe du dragon </TITLE> </HEAD> <BODY> <APPLET CODE=« Dragon.class » WIDTH=400 HEIGHT=400> </APPLET> </BODY> </HTML> On ouvre ensuite ce fichier sous Netscape ou bien directement par appletviewer DessinDragon.html

43 2.1 Le dragon documenté import java.awt.*; import java.applet.*:
public class Dragon extends Applet { /** * Methode de dessin du dragon. * </BR> * On obtient le dessin suivant : * <APPLET> CODE=« Dragon.class » WIDTH=300 HEIGHT=300> </APPLET> */ public void paint(Graphics g) { g.setColor(Color.red); drawDragon(g,20,100,100,200,200); } private void drawDragon(Graphics g, int n, int x, int y, int z, int t) { int u,v; if (n==1)‏ g.drawLine(x, y, z, t); else { u = (x + z + t - y) / 2; v = (y + t - z + x) / 2 drawDragon(g, n-1, x, y, u, v); drawDragon(g, n-1, z, t, u, v);

44 2.2 Le langage Java Java est dérivé de Kawa. Créé en 1995, la version actuelle est la 1.6 Java est fortement typé est orienté objet est compilé-interprété intègre des threads ou processus légers est sans héritage multiple MAIS avec implémentation multiple d’interfaces offre DORENAVANT de la généricité à la manière des templates de C++ (classes paramétrées)‏ Compilation - Interprétation Source compilé en langage intermédiaire (byte code) indépendant de la machine cible Byte code interprété par une machine virtuelle Java dépendant de la plate-forme

45 Info Notes élaborées par David et Dhaya 1h30

46 2.2 Le langage Java Avantages :
+ L ’exécution peut se faire en différé et/ou ailleurs, par téléchargement + Plus de mille classes prédéfinies qui encapsulent des mécanismes de base : structures de données : vecteurs, listes, ensembles ordonnés, arbres, tables de hachage, grands nombres outils de communication, comme les url, client-serveur facilités audiovisuelles, pour images et son des composants d ’interface graphique traitements de fichiers accès à des bases de données

47 2.3 Structure d ’1 programme
class HelloWorld { public static void main(String[] args) { System.out.println(« Hello World ! »); } Programme Java : constitué d ’un ensemble de classes groupées en paquetage (packages)‏ réparties en fichier chaque classe compilée est dans son propre fichier (un fichier dont le nom est le nom de la classe suffixée par .class)‏ Un fichier source java comporte : des directives d ’importation comme import java.io.*; des déclarations de classes

48 Fin CM2 année

49 Une classe est composée de :
déclaration de variables (attributs) // appelées parfois variables de classe définition de fonctions (méthodes)‏ déclaration d ’autres classes (nested classes)‏ les membres sont des membres de classe (static) des membres d ’objet (ou d ’instance)‏ Une classe a 3 rôles : 1- de typage, en déclarant de nouveaux types 2- d ’implémentation, en définissant la structure et le comportement d ’objet 3- de moule pour la création de leurs instances Une méthode se compose : des déclarations de variables locales ; d ’instructions Les types des paramètres et le type de retour constituent la signature de la méthode. Static int pgcd(int a, int b) { return (b==0) ? a : pgcd(b, a%b); }

50 Point d  ’entrée : Une fonction spéciale est appelée à l ’exécution .
Elle s ’appelle toujours main et a toujours la même signature : public static void main(String[] args) { … } Toute méthode, toute donnée fait partie d ’une classe (pas de variables globales). L ’appel se fait par déréférencement d ’une classe ou d ’un objet d ’une classe, de la façon suivante : Méthodes ou données de classe : par le nom de la classe. Math.cos() Math.PI Méthodes ou données d ’un objet : par le nom de l ’objet. Pile P; int x=2; … p.push(x); L ’objet courant est nommé this et peut-être sous-entendu s ’il n’y a pas d ambiguïté de visibilité. public void setX(int x) { this.x=x; } La classe courante peut-être sous-entendue pour des méthodes statiques. System.out.println() avec out, un membre statique de la classe System, et également un objet de la classe PrintStream avec println, une méthode d ’objet de la classe PrintStream.

51 2.4 Expressions, types, variables
Toute expression a une valeur et un type. Les valeurs sont : les valeurs de base les références, à des tableaux ou à des objets Un objet ne peut être manipulé en Java, que par une référence. Une variable est le nom d ’un emplacement mémoire qui peut contenir une valeur. Le type de la variable décrit la nature des valeurs de la variable. Si le type est un type de base, la valeur est de ce type. Si le type est une classe, la valeur est une référence à un objet de cette classe, ou d ’une classe dérivée. Exemple : Point p; déclare une variable de type Point, susceptible de contenir une référence à un objet de cette classe. P=new Point(4,6); L ’évaluation de l ’expression new Point(4,6) retourne une référence à un objet de la classe Point. Cette référence est affectée à p.

52 Toujours par valeur, ou bien par référence implicite.
Passage de paramètres Toujours par valeur, ou bien par référence implicite. Exemple : soit la méthode static int plus(int a, int b) { return a+b; } A l ’appel de la méthode, par exemple int c=plus(a+1,7), les paramètres sont évalués, des variables formelles (locales à la méthode-fonction) sont initialisées avec les valeurs des paramètres-expressions réels. Des occurrences des paramètres formels sont ainsi remplacées par des variables locales correspondantes. Par exemple, int aLocal=a+1; int bLocal=7; int résultat=aLocal+bLocal; Attention ! Les objets ou tableaux sont manipulés par des références. Un passage par valeur d ’une référence est donc comme un passage par référence. Si la valeur-référence ne sera pas modifiée, les valeurs membres de l ’objet référencé peuvent, elles, être modifiées et cela impacte le programme appelant. Exemple : static void incrementer(Point a){ a.x++; a.y++} Après l ’appel de incrementer(b), les coordonnées du point b sont incrémentées.

53 Info Fin cm-td n°4 Prise de note PAG

54 2.5 Types de base (primitifs)‏
A noter : Les caractères sont codés sur 2 octets en unicode. Les types sont indépendants du compilateur et de la plate-forme. Tous les types numériques sont signés sauf les caractères. Un booléen n ’est pas un nombre Les opérations sur les entiers se font modulo et sans erreur : byte b = 127; b += 1; // b = -128

55 Une variable se déclare en donnant d ’abord son type.
int i, j =5; float re, im; boolean termine; static int numero; static final int N = 12; A noter : Une variable peut-être initialisée Une variable static est un membre de classe. Une variable final est une constante. Tout attribut de classe est initialisé par défaut, à 0 pour les variables numériques, à false pour les booléennes, à null pour les références. Dans une méthode, une variable doit être déclarée avant utilisation. Elle n ’est pas initialisée par défaut. Dans la définition d ’une classe, un attribut peut-être déclaré après son utilisation.

56 Expressions Comme en C ou C++ :
radians = (degres/180) * Math.PI // conversion de degrés en radians « Bonjour » + «  Monde »; // string (i != 0) && (i % 2 == 0) // boolean, entier non null paire x = x +1; ++i i++ --j j-- j += 2; // j = j+2 j += j; // j = j + j max = (a > b) ? a : b; (x % 2 == 1)? 3*x+1 : x/2;

57 Tableaux C ’est un objet particulier. L ’accès se fait par référence et la création par new. Un tableau : se déclare, se construit (s ’alloue et s ’initialise)‏ et s ’utilise. L ’identificateur de type tableau se déclare par : int[] a; // vecteur d ’entiers double[][] m; // matrice de doubles -> La déclaration des tableaux comme en C ou C++ est acceptée : int a[]; double m[][]; Construction d ’un tableau par new : a = new int[n]; m = new double [n][p]; // n lignes, p colonnes Utilisation traditionnelle int i, j; m[i][j]=x; // ligne i, colonne j for(i = 0; i < a.length; i++)‏ System.out.print( a[i] );

58 Fin CM-4 poursuite TD Objectifs TD
2 fonctionnalités de vos mini-projets Sortie automatique du labyrinthe Modélisation diagramme de classe qui intègre cette fonctionnalités ainsi que celles qui sont sous-jascente à cette fonctionnalité Labyrinthe l l.sortieAutomatique(...); pivoter(droite, ...), pivoter(gauche), avancer, sortie? ... Placement de ces fonctionnalités Réalisation/traduction en langage Java [réalisation d'une interface Frame à-la-manière de HelloWorld, et d'une interface APPLET à-la-manière de FractaleDragon]

59 Fin CM3/TD Prise de note Guillaume Verstraete et Mr Donizetti Exposé des obligations TD et TP pour la sem 9 => Les fonctions itératives et automatiques Le diagramme de classe qui évolue Réalisation d’une interface frame et applet simpliste

60 Utilisation traditionnelle
int i, j = 45; m[i][j]=x; // ligne i, colonne j int [] a = new int[j]; for(i = 0; i < a.length; i++)‏ System.out.print( a[i] ); Tout tableau a un attribut length qui donne sa taille à la création. Distinguer : la déclaration, qui concerne la variable dont le contenu sera une référence sur un tableau, de la construction, qui crée l ’espace mémoire du tableau et retourne une référence sur cet espace mémoire de ce tableau. On peut fusionner déclaration et construction par initialisation énumérative : String[] jours = {«Lundi», «Mardi», «Mercredi», «Jeudi», «Vendredi», «Samedi», «Dimanche»}; Les instructions suivantes provoquent toujours une exception de la classe ArrayIndexOutOfBoundsException : a[a.length], a[-1];

61 Exercice prise en main du langage
Syntaxe i) Ecrire 2 façons de déclarer et d’initialiser 1 tableau contenant les 10 premiers entiers ii) Ecriture du programme qui manipulera a et b et qui affichera leurs contenus.

62 Exercice prise en main du langage
i) public class Test { public static void main(String [] args){ int [] a={1,2,3,4,5,6,7,8,9,10}; int [] b=new int[10]; for(int i=0; i < b.length;i++){ b[i]=i+1; } }

63 Exercice prise en main du langage
ibis) // autre manière plus capilo-tractée Public class Test { Public static void main(String [] args){ int [] a={1,2,3,4,5,6,7,8,9,10}; int [] b=new int[10]; for(int i=0; i < b.length;){ b[i]=++i; } }

64 Exercice prise en main du langage
ii) // Dans Test.java public class Test { Public static void main(String [] args){ int [] a={1,2,3,4,5,6,7,8,9,10}; int [] b=new int[10]; for (int i=0; i < b.length;){ b[i]=++i; } /* l’affichage dans le cas ou a et b sont de la même taille */ for (int i=0; i<a.length;i++){ System.out.println(‘’a[‘’+ i + ‘’] =’’ + a[i] + ‘’;’’); } } }

65 Exercice prise en main du langage
ii-bis) // Dans Test.java public class Test { Public static void main(String [] args){ int [] a={1,2,3,4,5,6,7,8,9,10}; int [] b=new int[10]; for (int i=0; i < b.length;){ b[i]=++i; } /* l’affichage dans le cas ou a et b ne sont pas forcément de la même taille */ for (int i=0; i< (a.length<b.length?b.length:a.length);i++){ if (i<a.length){System.out.println(a[i])} if (i<b.length){System.out.println(b[i])} } } }

66 Exercice surcharge Modifier la classe Array, de façon à ce que l’on affiche le contenu d’1 tableau t simplement par l’appel de : System.out.println(t);

67 Exercice surcharge public class Array { // tout un ensemble d’attr privés : exemple la collection des éléments // si Array a=new Array(type, taille); // j’y accède par a[i] … … public int length; // contient la taille de l’instance de ce tableau … public Array(Object o, int taille){ this.collection=new o.classname [taille]; // il faut faire un eval de la commande précédente, // seulement un éval d’une commande n’est pas triviale à réaliser en java (plus aisé en javascript, actionScript, // ou tout autre langage interprété) } public String toString(){ StringBuffer sb = new StringBuffer(); for (int i=0; i<this.length;i++){ sb.append(this.collection[i].toString()); } return sb.toString(); } }

68 Rmq - Exercice surcharge
Comment réaliser la surcharge ? Par des design pattern qui réalisent l’introspection et la modification dynamique des classes et composants des classes (attr ou primitives) ; Dansla version Tigre du langage, et tigre désigne la prochaine version du langage Java, il y aura la généricité et les macros. Ce n’est pas hasardeux de retrouver ces 2 évolutions majeures au sein d’une même version. En fait la macro permet de réaliser l’eval(nouvelle expression);. Ce faisant on réalise alors la généricité. Généricité étant le concept auquel nous nous sommes attaqués au travers de l’exercice ARRay précédent ;)

69 Matrices Les tableaux sont dynamiques dans toutes les dimensions (la mémoire peut -être allouée dynamiquement ). /** * Classe permettant de manipuler des matrices Canalda 1.0 */ public class Matrice { private int[][]m; * Creation d ’une matrice nulle dont la taille est donnee en parametre. n taille de la matrice Matrice#Matrice(int,int)‏ public Matrice(int n){ this.m = new int[n][n]; // de façon equivalente this(n,0)‏ };

70 /** * Creation d ’une matrice dont la taille et le contenu sont donnes en parametre. n taille de la matrice x valeur de chaque coefficient Matrice#Matrice(int)‏ */ public Matrice(int n, int x){ this.m = new int[n][n]; for(int i=0; i<n; i++)‏ for(int j=0; j<n; j++)‏ this.m[i][j]=x; }; * Transposition de matrice void Transposer(){ int n = m.length; for(int i=0; i<n; i++) { for(int j=i+1; j<n; j++) { int t = m[i][j]; m[i][j] = m[j][i]; m[j][i] = t; }

71 On obtient : $java Matrice 12 12 12
/** * Affichage d ’une matrice. */ public String toString(){ int n = m.length; StringBuffer sb = new StringBuffer(); for(int i=0; i<n; i++){ for(int j=0; j<n; j++){ sb.append(m[i][j] + «  »); }; sb.append(« \n »); return sb.toString; * Methode principale args arguments de la ligne de commande public static void main(String[] args){ Matrice a = new Matrice(3,12); System.out.print(a); Matrice b = new Matrice(3); System.out.print(b); } On obtient : $java Matrice 0 0 0

72 Instructions Affectation, instructions conditionnelles, aiguillages, itérations usuelles. Affectation : x = 1; y = x = x+1; Instructions conditionnelles if (C) S; if (C) S; else T; Itérations : while (C) S; do S while (C); for(E;C;G) S; Une instruction break; fait sortir du bloc où elle se trouve.

73 Traitement par cas : Blocs à étiquettes switch(C) { case ‘ ’:
nEspaces++; break; case ‘0’: case ‘1’: case ‘2’: case ‘3’: case ‘4’: case ‘5’: case ‘6’: case ‘7’: case ‘8’: case ‘9’: nChiffres++; break; default : nAutres++; } Blocs à étiquettes un: while (...){ deux: for(){ trois: while (…){ if (…) continue un; // reprend while extérieur if (…) break deux; // quitte boucle for continue: // reprend while intérieur

74 Info Mathieu Brousse à pris les notes du CM5

75 Question : Dans le cas d’1 for intégrant un continue, y-a-til reprise à l’itération courante ou bien à l’itération suivante ? Ecrire un petit programme qui vous permet de le vérifier Attention, il pourrait y avoir des risques de boucles infinies ?

76 Méthodes Chaque classe contient une suite non emboîtée de méthodes. Mais si on ne peut pas définir des méthodes à l ’intérieur de méthodes, on pourra définir des classes à l’intérieur des classes. static int next(int n){ if (n % 2 == 1) // n est impair return 3*n +1; // n est pair return n/2; } static int pgcd(int a, int b){ return (b == 0) ? A : pgcd(b, a%b); Une méthode qui ne retourne pas de valeur a pour type de retour le type void.

77 Surcharge On distingue :
Profil : le nom + la suite des types des arguments Signature : le type de retour + le profil Signature complète : signature + la visibilité (private, protected, public ou rien). Signature étendue : signature complète + les exceptions Un même identificateur peut désigner des méthodes différentes pour autant que leurs profils soient distincts. static int fact(int n, int p){ if (n == 0) // condition d ’arrêt du prg récursif return p; else // mot clef facultatif return fact(n-1, n*p); }; static int fact(int n){ return fact(n,1); } Il n ’y a pas de valeurs par défaut. Il faut donc autant de définitions qu’il y a de profils.

78 Visibilité des attributs et méthodes
Les membres (attributs ou méthodes) d ’une classe ont une visibilité définie par défaut et ont des modificateurs de visibilité : public protected private Par défaut, une classe a ses données ou méthodes accessibles dans le répertoire, plus précisément dans le paquetage (cf. + loin). Un attribut (donnée ou méthode) public est accessible dans tout code où la classe est accessible. protected est accessible dans le code des classes du même paquetage et dans les classes dérivées de la classe. Private n ’est accessible que dans le code de la classe. La méthode main doit être accessible de la machine virtuelle, elle doit donc être public.

79 Constructeurs Les objets sont instanciés au moyen de constructeurs. Toute classe a un constructeur par défaut, sans argument. Lors de la construction d ’un objet, l ’opérateur new réserve la place mémoire pour l ’objet et initialise les attributs à leur valeur par défaut. Le constructeur exécute le corps de la méthode, et retourne la référence de l ’objet créé. Exemple avec seulement le constructeur par défaut : class Pixel{ int x, y; } Utilisation : class TestPixel{ public static void main(String[] args){ Pixel p; // p est déclaré, mais indéfini p = new Pixel(); // p != null, p.x = p.y = 0 p.x = 4; p.y = 5;

80 Exemple avec un constructeur particulier :
class Pixel{ int x, y; Pixel(int x, int y){ this.x=x; this.y=y; }; public static void main(String[] args){ Pixel p, q; // p et q sont déclarés, mais indéfinis, p = q = null p = new Pixel(2,3); // p != null, p.x=2, p.y=3 q = new Pixel(); // erreur } La définition explicite d ’un constructeur fait disparaître le constructeur par défaut implicite. Si on veut garder le constructeur par défaut, il faut alors le déclarer explicitement : Pixel(){}; q = new Pixel(); // OK

81 Les données d ’un objet peuvent être des (références d ’) objets.
class Segment{ Pixel debut, fin; } Utilisation : public static void main(String[] args){ Segment s; // s indéfini s = new Segment(); // s != null, s.debut = s.fin = null Plusieurs constructeurs pour la même classe : Segment(){}; Segment(Pixel d, Pixel f){ this.debut=d; this.fin=f; Segment(int dx, int dy, int fx, int fy){ this.debut=new Pixel(dx,dy); this.fin=new Pixel(fx,fy); Noter que dans le 2ème constructeur, on affecte à debut et à fin les références d ’objets existants dans le 3ème constructeur, on crée des objets à partir de données de base, et on affecte leurs références.

82 Exemples d ’emploi : public static void main(String[] args){ Segment s; // s indéfini s = new Segment(); // s.debut = s.fin = null s.debut = new Pixel(2,3); s.fin = new Pixel(5,8); Pixel p = new Pixel(2,3); Pixel q = new Pixel(5,8); Segment t = new Segment(p,q); Segment tt = new Segment(new Pixel(2,3), new Pixel(5,8)); Segment r = new Segment(2,3,5,8); }

83 Fin CM 4 Prise de notes : promo 2008-2009 Yann delcroix rapporteur 1
Cedric Bonacina rapporteur 2

84 Début CM 5 Prise de notes : promo 2008-2009
François Dodeman rapporteur 1 Akram Salem rapporteur 2

85 Membres et méthodes statiques
Les attributs peuvent être des attributs de classe (static), des attributs d ’objets (ou d ’instance). Les attributs de classe static sont partagés par tous les objets de la classe. Il n ’en existe qu’un par classe au lieu de un pour chaque instance ou objet d ’une classe lorsqu’il s ’agit de membre d ’objets. Exemple d ’attributs static : un compteur du nombre d ’objets (instances) de la classe, un élément particulier de la classe, par exemple une origine. class Point{ int x, y; static Point origine = new Point(0,0); } Les méthodes peuvent aussi être ou ne pas être static. Les méthodes static sont invoquées en donnant le nom de la classe ou bien le nom d ’une instance de classe. Une méthode static ne peut pas faire référence à this. Elles sont utiles pour fournir des services (helper). Méthodes de la classe Math.

86 Exemples 1 public class Chrono{ private static long start, stop; public static void start(){ start = System.currentTimeMillis(); } public static void stop(){ stop = System.currentTimeMillis(); public static long getElapsedTime(){ return stop - start; Et on s ’en sert de la manière suivante : class TestChrono{ public static void main(String[] args){ Chrono.start(); for(int i=0;i<100000;i++)‏ for(int j=0;j<100000;j++); Chrono.stop(); System.out.println(«Duree = » + Chrono.getElapsedTime());

87 Exemples 2 class User{ String nom; static int nbUsers; static User[] allUsers = new User[10]; User(String nom){ this.nom = nom; allUsers[nbUsers++] = this; } void send(String message, User destinataire){ destinataire.handleMessage(message, this); }; void handleMessage(String message, User expediteur){ System.out.println(expediteur.nom + « dit » + message + « à » + this.nom); void sendAll(String message){ for(int i=0; i<nbUsers;i++){ if (allUsers[i] != this) send(message, allUsers[i]);

88 Exemples 2 (suite)‏ class User{ public static void main(String[] args){ User a=new User(« Pierre »), b=new User(« Anne »), c=new User(« Alex »), d=new User(« Paul »); a.send(« Bonjour », b); b.senAll(« Hello »); a.sendAll(« Encore moi »); } Donne à l ’exécution : Pierre dit « Bonjour » à Anne Anne dit « Hello » à Pierre Anne dit « Hello » à Alex Anne dit « Hello » à Paul Pierre dit « Encore moi » à Anne Pierre dit « Encore moi » à Alex Pierre dit « Encore moi » à Paul

89 Retour sur les membres et les méthodes statiques
Les attribut peuvent être : Des attributs de classes (static) Attribut d’objet (ou instance) Les attributs de classe static sont partagées par tout les objets de la classe et il est unique. Les méthodes peuvent aussi être ou ne pas être static. Les méthodes static sont invoquées en donnant le nom de la classe ou bien le nom d’une instance de classe. Une méthode static ne peut pas faire référence à this. Elles sont utiles pour fournir des services (helper). En clair : Le mot clé static devant une variable (ou méthode) indique que celle-ci n'appartient pas à une instance particulière de la classe. Les variables ou méthodes statiques appartiennent à la classe elle-même. On peux ainsi les utiliser sans avoir une instance créée. De nombreuses classes ont des membres ou méthodes statiques. Par exemple la classe Math : System.out.println(Math.PI); //affiche la valeur de PI sans besoin de créer une instance de la classe Math.

90 Chapitre « Les concepts objets »
Passage vers l ’objet

91 Données de base Description un type : entier, chaîne de car., réel, etc une valeur (12, « mon texte », 7.28)‏ Inconvénients ensemble de types limité typage statique pas de notion de sous-typage Type d ’une donnée Ensemble des valeurs possibles pour cette donnée =

92 Les produits cartésiens
Principe définir les données comme produit cartésien d ’autres données ex : entier x entier x chaine un Prod_Cart (ou enregistrement) = 1 n-uplet ex : (10, 20, « rose ») représente un point de l ’écran ((« Durand », « Paul »), (« Durand », « Anne »)) représente un couple Réutilisation utilisation d ’un constructeur de type produit cartésien un nom pour le type ensemble de champs nommés et typés

93 Produits cartésiens : exemple
Introduction d ’un type « livre » TYPE t_livre = PROD_CART ( titre: chaine auteur : chaine éditeur : chaîne année de parution : date nombre de page : entier prix : réel )‏ Utilisation si RefProlog donnée de type livre, alors RefProlog.titre désigne son titre (et vaut « The Art of Prolog »)‏

94 Notion de classe et d’objet
Comparaison : type => classe Donnée/variable => Objet (instance d ’un type) (instance d ’une classe)‏ champ => champ et une fonction est éligible à être un champ Exemple : RefProlog serait un objet de classe livre

95 Classes et types : premières différences
point de vue statique => les champs Classe : Point de vue statique : état les champs (avec valeur par défaut éventuelle)‏ les propriétés ou contraintes Point de vue dynamique : changements d ’états les méthodes (définies au niveau de la classe, mais s ’appliquent sur les objets de cette classe), avec d ’éventuelles pré-conditions et post- conditions

96 Classes : un exemple Personne Nom : chaîne Prénom : chaîne
DateDeNaissance : t_date SituationDeFamille : TYPE enuméré = (‘ célibataire ’, …)‏ Sexe : (‘ M ’, ‘ F ’)‏ créer(nom,prénom,date,sexe) // surcharge créer(nom,prénom,date,sexe,situation)‏ ModifierSituation(NouvelleSituation)‏ Sexe=‘ M ’ ou ‘ F ’ Nom <> «  » Rmq: si toto est un objet de classe personne, Modifier la situation de toto se fait par toto.ModifierSituation(« Marié »)‏

97 Vie et mort d ’un objet Un objet : Par classe 3 types de méthodes :
naît vie meurt Par classe 3 types de méthodes : constructeurs destructeurs … les autres => rien n’est possible sur un objet non créé => rien n’est possible sur un objet détruit

98 Persistance d ’un objet
Mort d ’un objet classique : appel de son destructeur arrêt du système qui l’a créé Inconvénients : panne maintenance évolution => Notion d ’objet persistant Un objet persistant est on objet dont l’existence continue après l ’arrêt du système qui l ’a créé

99 Variables et méthodes de classe
Cas général : champs propre à un objet impossibilité à des objets d’une même classe de partager des données => variables d ’une classe même donnée pour tous les objets de la classe => méthodes de classe ne s ’appliquent pas particulièrement à un objet => à voir comme des fonctions de bibliothèques

100 Retour sur la notion de classe
On appelle classe la structure d'un objet, c'est-à-dire la déclaration de l'ensemble des entités qui composeront un objet. Un objet est donc « issu » d'une classe, c'est le produit qui sort d'un moule. En réalité on dit qu'un objet est une instanciation d'une classe, c'est la raison pour laquelle on pourra parler indifféremment d'objet ou d'instance (éventuellement d'occurrence). Une classe est composée de deux parties : Les attributs (parfois appelés données membres) : il s'agit des données représentant l'état de l'objet Les méthodes (parfois appelées fonctions membres): il s'agit des opérations applicables aux objets Exemple : Si on définit la classe voiture, les objets Peugeot 406, Renault 18 seront des instanciations de cette classe. Il pourra éventuellement exister plusieurs objets Peugeot 406, différenciés par leur numéro de série. Mieux: deux instanciations de classes pourront avoir tous leurs attributs égaux sans pour autant être un seul et même objet. C'est le cas dans le monde réél, deux T-shirts peuvent être strictement identiques et pourtant ils sont distincts. D'ailleurs, en les mélangeant, il serait impossible de les distinguer...

101 Vers la réutilisabilité
Elève Personnel Nom Prénom Nom Prénom Année d’étude Fonction créer(nom,prénom)‏ créer(nom,prénom)‏ créer(nom,prénom,annéeEtude)‏ changerAnnéeDEtude(année)‏ créer(nom,prénom,fonc)‏ changerFonction(fonc)‏ Parties différentes Parties communes => Comment factoriser les parties communes ?

102 Héritage : introduction
Représentations possibles Personne Nom Prénom créer(nom,prénom)‏ Elève : Personne Personnel : Personne Année d’étude Fonction créer(nom,prénom,annéeEtude)‏ changerAnnéeDEtude(année)‏ créer(nom,prénom,fonc)‏ changerFonction(fonc)‏ Vocabulaire : Elève hérite/est une sous-classe/est une spécialisation de Personne Personne est une généralisation/super-classe d’Elève On emploie aussi les termes de classe mère et de classe fille

103 Héritage et sous-typage
Autre lecture de la relation d ’héritage : un objet d ’une classe fille est un objet de la classe mère => Tout objet d’un type d’une classe fille peut-être utilisé à la place d’un objet du type d’une classe mère Sur l ’exemple : créer peut s ’appliquer pour un élève ou pour le personnel ! La réciproque n ’est pas vraie

104 Redéfinition et liaison dynamique
Principe de la liaison dynamique : La méthode périmètre de la classe Quadrilatère est redéfinie dans Losange. Soit P de type Parallélogramme, L de type Losange et Q de type Quadrilatère : Q <- P.Périmètre() calcule l1+l2+l3+l4 Q <- L.Périmètre() calcule 4*l1 Quadrilatère l1, l2, l3, l4 : réels périmètre() { périmètre=l1+l2+l3+l4} créer(p1,p2,p3,p4)‏ Parallélogramme : Quadrilatère Losange:Quadrilatère périmètre() {Périmètre=4*l1}

105 Classes et méthodes abstraites
Une classe abstraite C est une classe dont les seuls objets qui peuvent en être membres sont membres d’une sous-classe de C. Corollaire : il n ’est pas possible de créer un objet de classe C si C est une classe abstraite Une méthode abstraite est une méthode dont la définition n’est pas donnée dans la classe courante mais devra l’être dans des classes filles Toute classe contenant au moins une méthode abstraite est une classe abstraite

106 Classes et méthodes abstraites
Exemple : Classe abstraite Point { privé x, y : ENTIER Point(){}; Point(Valx, Valy : ENTIER) { // constructeur à this.x <- Valx ; // paramètres this.y <- Valy; } public procédure setX(Valx : ENTIER); // deux méthodes public procédure setY(Valy : ENTIER); // abstraites };

107 Héritage : disjonction ou recouvrement
Si un même objet ne peut pas être membre de plusieurs sous-classes d ’une même classe, on parle d ’héritage disjoint ŒUVRE d ’art Tableau Morceau de musique

108 Héritage : disjonction ou recouvrement
Sinon on parle d ’héritage avec recouvrement Bâtiment Professionnel Habitation

109 Héritage multiple Il y a héritage multiple si une classe peut hériter de plusieurs autres classes impossible avec Java Morceau de musique compositeur partition Livre auteur texte ŒUVRE d ’art

110 Retour sur l’héritage multiple
Si on avait class C extends A et extends B; ce serait de l‘héritage multiple mais on ne peut pas le faire pour la raison qu'il peut y avoir des ambigüités sources de bugs comme dans l'exemple en C++. Ici, dans D, si on fait un appel à l'attribut a, on ne sait pas s'il s'agit du a de B ou du a de C En fait, l‘héritage multiple est délicat d'utilisation et par ailleurs, les exemples où l‘héritage multiple se trouve utile sont assez rares. C'est pour cette raison que l'on ne trouve pas d'héritage multiple en java.

111 Héritages propriétés Transitivité Non réflexif Non symétrique
Si A hérite de B et B hérite de C alors A hérite de C Non réflexif Une classe ne peut pas hériter d’elle même Non symétrique Si A hérite de B alors B ne peut pas hériter de A Corollaire Un cycle dans une relation d ’héritage est impossible. Les relations d’héritages forment un DAG (Graphe dirigé acyclique)‏

112 Classes et méthodes terminales
Une classe terminale est une classe dont aucune classe ne peut hériter. Une méthode terminale est une méthode qui ne peut pas être redéfinie. Un champ terminal d’une classe est une constante.

113 Liens entre classe Comment ?
Par les champs, en déclarant un champ de classe A dans une classe B Dans les méthodes, en déclarant une variable de classe A dans une méthode de la classe B Par la définition explicite d’une relation exemple : Enseignant Matière nom prénom nom volume horaire

114 Agir sur un objet d’une classe liée
Actions possibles lire la valeur d ’un champ : destination <- nom_objet.nom_champ modifier un champ nom_objet.nom_champ <- nouvelle_valeur exécuter une méthode [résultat <- ] nom_objet.nom_méthode([paramètre d ’entrée]*)‏ Remarques le symbole d ’affectation est ici <- le texte entre crochet est optionnel et * signale 0 itération ou n itérations

115 Actions sur objet : constat
Rôle des méthodes factoriser du code commun avoir un typage plus fort (ne s’applique que sur les objets de la classe C dans laquelle elle est définie, ou d’une classe héritant de C)‏ n’autoriser que certains changements d’états sur un objet Mais possibilité d’intervenir directement depuis l’« extérieur » sur un champ d’une méthode (annule le dernier point)‏ n’est pas adapté à la réutilisabilité lorsque la représentation des données doit être modifiée (ex: ensemble de car ou d ’entiers)‏

116 Gestion des droits d ’accès
Conséquence du constat précédent pour chaque champ et chaque méthode, possibilité de définir des droits d’accès pour les autres classes

117 Encapsulation Définition : Principe :
modifier les champs d ’un objet n ’est possible que par l ’intermédiaire des méthodes définies directement ou par héritage dans la classe de cet objet Principe : les champs sont tous privés les méthodes mises à la disposition des autres classes sont déclarées publiques NB : si la classe a vocation à être utilisée comme une classe mère, certains champs et méthodes pourront être protégés

118 Encapsulation Avantages :
n’autoriser que certains changements d’états pour un objet possibilité de modifier la représentation interne d ’une classe (les champs) sans devoir refaire tous les projets ou programmes qui utilisent la classe Conséquences : pour diffuser au public une classe, préciser : nom et rôle de la classe profiles et rôles des différentes méthodes publiques si nécessaire, rôle des champs et méthodes protégées

119 Retour sur l’ accessibilité
Java définit quatre niveaux d'accès pour les variables d'instances (données membres) et les méthodes : public : un élément public est accessible de partout et sans aucune restriction. Certaines classes (comme la classe principale main) doivent obligatoirement être déclarées publiques (pour pouvoir exécuter l'application...) protected : un élément protected (protégé) est accessible uniquement aux classes d'un package et à ses classes filles private : un élément private (privé) est accessible uniquement au sein de la classe dans laquelle il est déclaré. Ces éléments ne peuvent être manipulés qu'à l'aide de méthode spécifiques appelés accesseur (getteur) et mutateur (setteur). La notion d'accesseur : Un accesseur est une méthode permettant de récupérer le contenu d'une donnée membre protégée. Un accesseur, pour accomplir sa fonction : doit avoir comme type de retour le type de la variable à renvoyer ne doit pas nécessairement posséder d'arguments Une convention de nommage veut que l'on fasse commencer de façon préférentielle le nom de l'accesseur par le préfixe get, afin de faire ressortir sa fonction première. La notion de mutateur : Un mutateur est une méthode permettant de modifier le contenu d'une donnée membre protégée. Un mutateur, pour accomplir sa fonction : doit avoir comme paramètre la valeur à assigner à la donnée membre. Le paramètre doit donc être du type de la donnée membre ne doit pas nécessairement renvoyer de valeur (il possède dans sa plus simple expression le type void) Une convention de nommage veut que l'on fasse commencer de façon préférentielle le nom du mutateur par le préfixe set.

120 Réutilisation des structures de données
Problème liste d ’entiers ajouter un élément(entier); enlever le premier élément; donner la longueur de la liste; trier numériquement les éléments de la liste ; liste de caractères ajouter un élément(caractère); trier alphabétiquement les éléments de la liste ; Parties différentes => héritage inutilisable ...

121 Interface Définition Implantation Utilisation
une interface est un ensemble nommé de profils de méthodes Implantation une classe implante une interface si elle : le déclare implante toutes les méthodes spécifiées dans l ’interface Utilisation si une classe est reliée à un type d’interface donné, elle peut être reliée à toute classe implantant cette interface

122 Généricité Principe : paramétrer une classe par une autre => Définition d ’un objet A : Liste <ENTIER> Généricité contrainte but permettre l’utilisation d ’une fonction de la classe paramètre Liste <OBJECT> ajouter un élément enlever le premier élément calculer la longueur de la liste ENTIER

123 Généricité contrainte : exemple
Booléen x : booléen Liste <OBJECT -> ordre > ajouter un élément enlever le premier élément calculer la longueur de la liste ordonner la liste = faire un tri à bulle en utilisant la méthode comparer définie sur les éléments ENTIER x: entier booléen comparer(y:entier)‏ CHAINE x:chaine booléen comparer(y:chaine)‏ A : Liste <booléen> impossible B : Liste <entier> possible, B.ordonner() trie numériquement C : Liste <chaîne> possible, C.ordonner() trie alphabétiquement

124 2.6 Héritage : généralités
L ’héritage consiste à faire profiter tacitement une classe dérivée D des attributs et des méthodes d ’une classe de base B. La classe dérivée possède les attributs de la classe de base (et peut y accéder sauf s ’ils sont privés). La classe dérivée possède les méthodes de la classe de base (même restriction). La classe dérivée peut déclarer de nouveaux attributs, et déclarer et définir de nouvelles méthodes La classe dérivée peut redéfinir des méthodes de la classe de base. La méthode redéfinie masque alors la méthode de la classe de base. Dérivation par extends Toute classe dérive, directement ou indirectement de la classe Object. L ’arbre de dérivation est visible dans les fichiers créés par javadoc. La relation d ’héritage est transitive. B D

125 Retour sur la notion d’héritage
L'héritage (en anglais inheritance) est un principe propre à la programmation orientée objet, permettant de créer une nouvelle classe à partir d'une classe existante. Le nom d'"héritage" (pouvant parfois être appelé dérivation de classe) provient du fait que la classe dérivée (la classe nouvellement créée) contient les attributs et les méthodes de sa superclasse (la classe dont elle dérive). L'intérêt majeur de l'héritage est de pouvoir définir de nouveaux attributs et de nouvelles méthodes pour la classe dérivée, qui viennent s'ajouter à ceux et celles héritées. Par ce moyen on crée une hiérarchie de classes de plus en plus spécialisées. Cela a comme avantage majeur de ne pas avoir à repartir de zéro lorsque l'on veut spécialiser une classe existante. Il est possible de représenter sous forme de hiérarchie de classes, parfois appelée arborescence de classes, la relation de parenté qui existe entre les différentes classes. L'arborescence commence par une classe générale appelée superclasse (parfois classe de base, classe parent, classe ancêtre, classe mère ou classe père, les métaphores généalogiques sont nombreuses). Puis les classes dérivées (classe fille ou sous-classe) deviennent de plus en plus spécialisées. Ainsi, on peut généralement exprimer la relation qui lie une classe fille à sa mère par la phrase "est un" (de l'anglais "is a"). Ici, un lapin est un herbivore qui est un animal. De meme, une hyène et un lion sont tout deux des carnivore et des animaux.

126 TP 5 Groupe A Lundi 17 novembre er Rapporteur : Sofiane AIT-TALEB 2eme Rapporteur : Christophe Margaine Déroulement de la séance : Appel et nomination des rapporteurs Tour de table Validation des diagrammes de classe

127 Composition des groupes

128 Sphere light Cahier des charges : validé. Diagramme de classe : à refaire. Graphisme : terminé. Diagramme UML : à faire. Partie codage : à commencer. Objectifs à court terme : version texte monojoueur monoposte. Remarque : Etant donné la taille du groupe (6 personnes), le projet devra être abouti sur son ensemble et devra contenir une version multijoueur et multiposte (réseau).

129 Renaissance Cahier des charges : validé. Diagramme de classe : à valider. Graphisme : terminé. Diagramme UML : commencé. Partie codage : commencé. Objectifs à court terme : version texte monojoueur monoposte. Remarque : Projet original en ce qui concerne la partie multi joueur puisque c’est le seul groupe à proposer une collaboration entres les différents joueurs.

130 Conte macabre Cahier des charges : a valider. Diagramme de classe : a valider. Graphisme : à commencer dès la version texte fonctionnelle. Diagramme UML : terminé. Partie codage : à commencer. Objectifs à court terme : version texte monojoueur monoposte. Remarque : Groupe réduit donc chacun des membres va devoir participer au codage de l’application.

131 Le monde de Clara Cahier des charges : version 2 à valider. Diagramme de classe : commencé. Graphisme : commencé. Diagramme UML : commencé. Partie codage : à commencer. Objectifs à court terme : version texte monojoueur monoposte. Remarque : Problème de communication avec un des membres du groupe (groupe de 6 personnes).

132 Diagrammes de classe de Sphere Light

133 Diagrammes de classe de Renaissance

134 Diagrammes de classe du Monde de Clara

135 TP 5 Groupe B Lundi 17 novembre 2008 1er Rapporteur : Jules EID 2eme Rapporteur : Meriza LENANDA
Déroulement de la séance : Appel et nomination des rapporteurs Détails de la notation Tour de table Validation des diagrammes de classe

136 Détails de la notation Explicitation du détail des notes : ‐ Cahier des charges : 1/6 de la note ‐ Délivrables (java doc, diagramme de classe, autre, …) 2/6 à 3/6 et donne déjà une note sur avec les compétences de conception notée sur 12 au sein de l’unité de l’enseignement. ‐ Les diagrammes : 1/6 de la note. ‐ Notes rendu 1 et rendu 2 : o R1 : 0,75/6 ou 0,66/6 de la note. o R2 : 0.25/6 ou 0,34/6 de la note. A préciser : une petite flexibilité du barème et des changements restent possibles.

137 The wind up Cahier des charges : Il a été validé lors de la séance précédente. Diagramme de classe : La version beta est faite mais reste tout de même à être validée voir modifier durant le cours de la séance (mono‐joueur et monoposte) Diagramme de gant : Fait mais a modifier au niveau de l’assignation des ressources. Diagramme des cas d’utilisation : Déjà fait précédemment. Diagramme de séquence : Encore en cours de réalisation. Le groupe cherche les différentes manières de communiquer avec le diagramme de classe. Graphisme : Il a été abordé assez rapidement dans la première version du cahier des charges. Le groupe se concentre pour le moment sur la version texte. (Idée en tête) Objectif : Mettre les documents réalisés au propre. Réalisation pendant la semaine de version texte

138 Buster et Charlie Cahier des charges : Il a été validé lors de la séance précédente. Diagramme de classe : En cours de réalisation pour la partie jeu mono‐joueur, monoposte Diagramme de gant : Réalisé jusqu'à la date de rendu du jeu. Diagramme des cas d’utilisation : presque finalisé à ce jour. Diagramme de séquence : Tous les éléments du diagramme sont présents, il faut maintenant les mettre sous une forme standard. Graphisme : L’interface est définie, la disposition des éléments aussi. Le niveau 1 est fait. Pour les niveaux 2 et 3 la forme globale reste la même mais quelques éléments seront à rajuster. Objectif : Finir la présentation du niveau 1. Faire les algorithmes pour les niveaux 2 et 3. Créer le diagramme de classe n1 n2 n3 Faire des recherches pour la mise en réseau (multiposte) Intégrer le graphisme du jeu.

139 Buster et Charlie bis Cahier des charges : Il a été validé lors de la séance précédente. Diagramme de classe : A été réalisé pour la partie Mono‐post, mono‐joueur en totalité. Diagramme de gant : Il est déjà réalisé mais reste peut être à étoffer. Diagramme Cas d’utilisation : Déjà réalisé pour le niveau 1. Diagramme de séquence : Déjà réalisé pour le niveau 1. Des tests avec Eclipse ont été réalisés de manière à prévoir une base pour la phase de réalisation. Le Graphisme en cours de réalisation : L’interface générale du jeu est faite, il reste encore à faire les différents boutons présents à l’écran ainsi que les personnages, les pièces et autre petit éléments du jeu. Objectif : Programmation du niveau 1 du jeu en monoposte et mono‐joueur en mode texte. Elaboration et Création du diagramme de compilation. Terminer toute la partie graphisme du jeu. Léger problèmes à régler dans la gestion de projets : répartition des taches aux membres du groupe.

140 TP 5 Groupe C Lundi 17 novembre er Rapporteur : Pierre-Emmanuel REMY 2eme Rapporteur : Aki IMADA Déroulement de la séance : Appel et nomination des rapporteurs Tour de table Validation des diagrammes de classe

141 Tour de table : itravel ‐Diagramme de classe : fini
‐Classe full‐abstrait : interface ‘’Piece’’ ‐Test unitaire : pas encore. 2) Warning Groupe 1 (BD, OM, AM, AT) : ‐Diagramme de classe : Terminé. ‐Classes full‐abstrait : Non fait Groupe 2 (PM, SP, PER) : ‐Diagramme de classe : Presque terminé. ‐Classe full‐abstrait : Non fait ‐Diagramme de Gantt : Terminé.

142 Validation de P. Canalda :
itravel Diagramme de classes : L’important est de savoir quelle classe est associée à quelle classe : faire un choix d’association la plus efficace entre plusieurs possibilités. problème d’association entre les classes Joueur, Puzzle et Volume La classe Volume correspond à l’objet qui se trouve à droite de l’écran, indiquant le nombre de vie du joueur. Quand le joueur place la pièce au mauvais endroit, le nombre de vie (donc le volume) diminue. La classe Volume, est‐elle complètement à part ? Est‐elle attachée à la classe Puzzle ? Ou à la classe Joueur ? D’abord, la classe Piece est associée à la classe Case par son attribut « coordonneesPiece ». Ensuite, le joueur déclenche la fonction « placerPiece » dans la classe Piece par le fait d’activer sa fonction « deplacerPiece ». Et, ce fait va faire appel à la classe Volume. Donc, cette classe est plutôt liée au joueur.

143 - Le point de vue de programmation :
Si Volume est associé au Puzzle : Lorsque le joueur passe au niveau supérieur (c‐a‐d, à un nouveau Puzzle), il faudrait aussi créer une nouvelle classe Volume. Si Volume est associé au Joueur : Lorsque le joueur avance le niveau, il suffit d’affecter le nombre de vie (+ 2, + 3 etc...). Il vaudrait donc mieux de mettre une relation composition entre la classe Volume et la classe Joueur. problème d’association entre les classes Joueur, Puzzle et Ipod La classe Ipod correspond à l’objet qui se trouve à gauche de l’écran, affichant une pièce aléatoirement. Le joueur utilise la molette pour choisir et valider l’emplacement de la pièce. Si Ipod est associé au Puzzle : Chaque fois que le joueur change, il faut appeler la classe Ipod et dire que l’Ipod est associé à tel joueur. Si Ipod est associé au Joueur : Chaque joueur est associé à un Ipod.

144 Cela paraît plus logique de mettre une relation composition entre la classe Ipod et la classe Joueur. ‐ On peut avoir également la classe I_jeu, I_case, I_volume, I_Ipod etc... comme classe full abstrait. répartition de classes Anaïs : Case, InterfacePiece, Piece, PieceBonus Aki : Volume, Puzzle Guillaume : Jeu, Joueur, Homme, Machine Olivier : Ipod, Ecran, TouchesDeDeplacement, ToucheDeValidationPiecePourPlacement Pierre‐Damian : PieceMalus, PieceNormale, InversionTouche, RotationPuzzle

145 Diagrammes de classe i-Travel :

146 Diagrammes de classe warning :

147 Diagrammes de classe warning bis :

148 Info Prises de notes CM6 : Foued, Huu Hoaï

149 Info Fin CM du 19 novembre 2007

150 Le résultat est : $java TestBase B 2 3 5
class Base { private int p=2; int x=3, y=5; public String toString(){return «B »+p+«  »+x+«  »+y;}; int somme(){return x+y;}; } class Der extends Base{ int z=7; public String toString(){return «D» »+p+«  »+x+«  »+y+«  »+z;}; public class TestBase{ Base b=new Base(); Der d=new Der(); System.out.println(b); System.out.println(b.somme()); System.out.println(d); System.out.println(d.somme()); Le résultat est : $java TestBase B 2 3 5 8 D

151 Usages class Point{ … Une classe dérivée représente
une spécialisation de la classe de base. Mammifère dérive de vertébré, matrice symétrique dérive de matrice. un enrichissement de la classe de base. Un segment coloré dérive d ’un segment. Un espace vectoriel normé dérive d ’un espace vectoriel. Un article a un prix, un vêtement est un article qui a une taille. Un aliment est un article qui a une date de péremption. Une classe de base représente des propriétés communes à plusieurs classes. Souvent c ’est une classe abstraite, c ’est à dire sans réalité propre, i.e. sans instance possible. une figure est une abstraction d ’un rectangle et d ’une ellipse. Un sommet est un nœud interne ou une feuille. Les mammifères eux-mêmes sont une abstraction. Un type abstraite de données est une abstraction d ’une structure de données. Point épais : exemple de dérivation class Point{

152 ... Point épais : exemple de dérivation class Point{
private int x,y; Point(int x,y){ this.x=x; this.y=y; }; void translater(int dx, int dy) { this.x+=dx; this.y+=dy; public String toString(){ return(this.x+«, »+this.y); } class PointEpais extends Point{ int epaisseur; PointEpais(int x, int y, int e){ super(x,y); this.epaisseur=e; ... ... public String toString(){ return super.toString()+«, »\ +this.epaisseur; } void epaissir(int i){ this.epaisseur+=i; public static void main(String[]\ args){ PointEpais a=new \ PointEpais(3, 5, 1); System.out.println(a); //3,5,1 a.translater(5,-2); System.out.printl(a); //8,3,1 a.epaissir(5); System.out.printl(a); //8,3,6

153 Dans l ’exécution d’un constructeur, le constructeur de la classe de base est exécuté en premier. Par défaut, c ’est le constructeur sans argument de la classe de base. On remonte récursivement jusqu’à la classe mère terminale Object. L ’appel d ’un autre constructeur de la classe de base se fait au moyen de super(…). Cette instruction doit être la première dans l ’écriture du constructeur de la classe dérivée. En d ’autres termes, si cette instruction est absente, c est l ’instruction super() qui est exécutée en premier. This et super this et super sont des références sur l ’objet courant. Super désigne l ’objet courant avec le type père. Il indique que la méthode invoquée ou bien le membre d ’objet désigné doit être recherchée dans la classe de base. Il y a des restrictions d ’usage comme : f(super) qui est interdit, i.e. on ne peut pas passer cette fonctionnalité par paramètre. L ’usage de this et super sont spéciaux dans les constructeurs.

154 Destruction des objets
La destruction des objets est effectuée : soit implicitement et automatiquement par le ramasse-miettes, de façon asynchrone, avec un processus léger (Thread) de basse priorité ; soit explicitement par la spécification et l ’invocation de la méthode finalize() qui permet de spécifier des actions à effectuer au moment de la destruction de l ’objet (opérations de nettoyage, fermeture des fichiers, etc.). L ’appel au ramasse-miettes peut être forcé par l ’appel System.gc(); class Disque{ finalize(){ System.out.println(« Disque détruit »); }

155 Délégation class Point{ private int x,y;
Point(int x,y){ this.x=x; this.y=y; }; void translater(int dx, int dy) { this.x+=dx; this.y+=dy;}; public String toString(){ return(this.x+«, »+this.y);} } class Disque{ Point centre; int rayon; Disque(int x, int y, int rayon){ this.centre=new Point(x,y); this.rayon=rayon; return centre.toString+« ,»+rayon; void translater(int dx, int dy){ centre.translater(dx,dy);//délégation } finalize(){ System.out.println(« Disque détruit »); class TestDisque{ public static void main(String[] args){ Disque d =new Disque(3,5,1); System.out.println(d);//3,5,1 d.translater(5,-2); System.out.println(a);//8,3,1

156 Redéfinition Une méthode redéfinie est une méthode d ’une classe dérivée qui a même signature que la méthode mère, i.e. même : nom; suite des types de paramètres; type de retour. De plus : Les exceptions levées doivent aussi être levées par la méthode de la classe mère, et être au moins aussi précise (règle logicielle); la visibilité de la méthode doit être au moins aussi bonne que celle de la méthode de la classe mère (pas de restriction de visibilité). En cas de redéfinition, la méthode invoquée est déterminée dynamiquement en fonction du type de l ’objet à la création. Ce mécanisme est appelé liaison tardive. (exemple de la location de voitures et de camions). En cas de redéfinition, la méthode de la classe de base n ’est plus accessible à partir de l ’objet appelant : la méthode de la classe de base est masquée.

157 CM

158 public class Gamma extends Beta{
Exemple : public class Alpha{ void essai(Alpha a){ System.out.println(« alpha »);} } public class Beta extends Alpha{ void essai(Beta b){ System.out.println(« beta »);} public static void main(String[]\ args){ Beta b=new Beta(); Alpha c=new Alpha(); b.essai(c); public class Gamma extends Beta{ void essai(Alpha a){ System.out.println(« gamma »);} public static void main(String[]\ args){ Beta d=new Gamma(); Alpha e=new Gamma(); d.essai(e); } On obtient : $java Beta alpha $java Gamma gamma

159 Fin cm 5 Voir les 2 transparents précédents et traiter tout spécialement le précédent

160 Le transtypage Le transtypage
modifie le type de la référence à un objet; n ’affecte que le traitement des références, c ’est-à-dire qu’il ne change jamais le type de l’objet ; est implicite ou explicite. Principe de base : Point s = new PointEpais(5,7,1); Commentaires : cette règle fonctionne aussi si B est une interface et D implémente B; la relation est transitive; cette règle s’applique aussi aux paramètres d ’une méthode : pour C f(B b){…} l ’appel f(d) est possible si d est de classe D (qui dérive de B) ; cette règle s’applique également aux valeurs de retour d ’une méthode : pour r = f(b); si r est d ’une superclasse de C.

161 Intérêt du transtypage
Le transtypage explicite d’une référence n’est valide que si l’objet sous-jacent est d’une classe dérivée : Point s = new PointEpais(5,7,1); PointEpais t; t=s; // Erreur t=(PointEpais) s; // Ok Types et classes ne sont pas la même chose : « Variables have type, objects have class »; un objet ne change jamais de classe les références peuvent changer de type la vérification des types est statique (à la compilation); la détermination de la méthode à invoquer est dynamique (à l ’exécution). Intérêt du transtypage Si une variable x de type B contient une référence à un objet d’une classe dérivée D de B, seuls les attributs et les méthodes dont le nom est connu dans la classe B sont accessibles par la variable x. Si m est une telle méthode, l’appel de x.m() invoque la méthode m telle qu’elle est définie dans la classe de l’objet référencé par x. Ici, la méthode m telle qu’elle est définie dans D : c ’est le polymorphisme. Le transtypage permet: l’encapsulation, en rendant inaccessible les détails de D; l ’abstraction, en utilisant des méthodes génériques qui sont spécialisées dans les classes dérivées.

162 Héritage : interfaces Une interface
n ’a que des méthodes abstraites et tacitement publiques; et n ’a que des données static immuables (final). Une interface sert à spécifier des méthodes qu’une classe doit avoir, sans indiquer comment les réaliser. C’est le point ultime de l’abstraction. C’est un style de programmation à encourager : Program to Interfaces Exemple : une classe rectangle, class Rectangle{ double largeur, hauteur; Rectangle(double largeur, double hauteur){ this.largeur = largeur; this.hauteur = hauteur;} double getAire(){ return largeur * hauteur;} public String toString() { return «Aire =»+getAire();} }

163 Et une classe ellipse donnée par,
class Ellipse{ double largeur, hauteur; Ellipse(double largeur, double hauteur){ this.largeur = largeur; this.hauteur = hauteur;} double getAire(){ return largeur * hauteur * Math.PI/4;} public String toString() { return «Aire =»+getAire();} } Comme nous l’avons déjà vu, notamment avec l’exemple de la location de voitures et de camions, nous devons déterminer une abstraction commune en terme de membre et de méthodes. Aujourd’hui nous allons plus loin en rajoutant un niveau d’abstraction. Ces 2 classes ont alors une abstraction commune qui : définit les méthodes de même implémentation; déclare les méthodes communes et d ’implémentation différentes. L’ interface Form interface Form{ double getAire(); String toString(); }

164 La classe abstraite AbstractForm définit l’implémentation des membres et des méthodes à la déclaration et la définition commune, i.e. les membres largeur et hauteur, ainsi que la méthode toString() et la méthode du constructeur : abstract class AbstractForm implements Form{ double largeur, hauteur; AbstractForm(double largeur, double hauteur){ this.largeur = largeur; this.hauteur = hauteur;} public String toString() { return «Aire = »+getAire();}} Les méthodes abstraites (déclarées dans l’interface et non définies dans l ’implémentation) sont implémentées dans chaque classe concrète : class Rectangle extends AbstractForm{ Rectangle(double largeur, double hauteur){ super(largeur,hauteur);} public double getAire(){ return largeur * hauteur;}} et class Ellipse extends AbstractForm{ Ellipse(double largeur, double hauteur){ double getAire(){ return largeur * hauteur * Math.PI/4;}}

165 1 2 3 … n On se sert de ces classes dans : …
AbstractForm r=new Rectangle(6,10); Form c=new ellipse(3,5); System.out.println(r); System.out.println(c); ou bien dans : Form[] a= new Form[5]; a[0]=new Rectangle(6,10); a[1]=new ellipse(3,5); for(int i=0;i<a.length;i++;)‏ System.out.printl(a[i]); 1 2 3 n

166 Instanceof Dans l’exemple précédent, lorsque une référence peut pointer sur des types différents (c ’est le cas de a[i] qui peut référencer un objet de classe Ellipse ou bien Rectangle), on peut tester le type d ’un objet à l ’aide de instanceof : Form f=new Rectangle(6,10); if (f instanceof Rectangle) {…}; // vrai if (f instanceof Ellipse) {…}; // faux l ’opérateur instanceof est sous-jacent au concept de polymorphisme. Il s ’agit, dans certains traitements liés à une variable polymorphe de connaître le type instantané associé afin d ’invoquer une méthode ou adresser un membre disponible. Il ne faut pas abuser de instanceof, autant que faire se peut.

167 Exemple d ’interface : exercice
On se propose de faire 2 implémentations des matrices générales et des matrices symétriques. Elles doivent autoriser des constructions (au moins 2 distinctes), un affichage, une affectation d ’élément, une addition de 2 matrices, une transposition. Pour vous aider dans votre quête je vous rappelle l ’implémentation que nous avons déjà réalisée par le passé : public class Matrice { int n; int [][] m; public Matrice(int n){ this.n=n; this.m=new [n][n]; } public Matrice(int n, int x){ this.m=new int[n][n]; for(int i=0; i<n; i++)‏ for(int j=0; j<n; j++) this.m[i][j]=x; public void transposer(){ for(int i=0; i<n; i++)‏ for(int j=i+1; j<n; j++) { int t=m[i][j]; m[i][j]=m[j][i]; m[j][i]=t; } public String toString(){ StringBuffer sb = new StringBuffer(); for(int i=0; i<this.n; i++)‏ for(int j=0; j<this.n; j++) { sb.append(m[i][j]); sb.append(«  »); sb.append(«  \n»); return sb.toString();

168 Exemple d ’interface : exercice
On se propose de faire 2 implémentations des matrices générales et des matrices symétriques. Elles doivent autoriser des constructions (au moins 2 distinctes), un affichage, une affectation d ’élément, une addition de 2 matrices, une transposition. Pour vous aider dans votre quête je vous rappelle l ’implémentation que nous avons déjà réalisée par le passé : public class Matrice { int n; int [][] m; public Matrice(int n){ this.n=n; this.m=new [n][n]; } public Matrice(int n, int x){ this.m=new int[n][n]; for(int i=0; i<n; i++)‏ for(int j=0; j<n; j++) this.m[i][j]=x; public void transposer(){ for(int i=0; i<n; i++)‏ for(int j=i+1; j<n; j++) { int t=m[i][j]; m[i][j]=m[j][i]; m[j][i]=t; } public String toString(){ StringBuffer sb = new StringBuffer(); for(int i=0; i<this.n; i++)‏ for(int j=0; j<this.n; j++) { sb.append(m[i][j]); sb.append(«  »); sb.append(«  \n»); return sb.toString();

169 Interface Matrice{//Matrice d ’entiers Matrice add(Matrice a);
void setAt(int i, int j, int valeur); void transposer(); } Deux implémentations, à savoir des matrices générales et des matrices symétriques se partagent une classe abstraite commune public abstract class AbstractMatrice implements Matrice{ int[][] m; AbstractMatrice(int n){ this.n=n; this.m=new [n][n]; } AbstractMatrice(int n, int x){ this.m=new int[n][n]; for(int i=0; i<n; i++)‏ for(int j=0; j<n; j++) m[i][j]=x; (à suivre)‏ (suite)‏ public String toString(){ StringBuffer sb = new StringBuffer(); for(int i=0; i<n; i++)‏ for(int j=0; j<n; j++) { sb.append(m[i][j]); sb.append(«  »); } sb.append(«  \n»); return sb.toString();

170 public class GenMatrice extends AbstractMatrice{ GenMatrice(int n){
Les classes spécifiques se contentent d’implémenter les autres méthodes : public class GenMatrice extends AbstractMatrice{ GenMatrice(int n){ super(n);} GenMatrice(int n, int x){ super(n,x);} public Matrice add(Matrice a){ int n=m.length; Matrice r=new GenMatrice(n); for(int i=0;i<n;i++)‏ for(int j=0;j<n;j++)‏ r.setAt(i,j,m[i][j]+a.m[i][j]); return r; } public void setAT(int i, int j, int valeur){ m[i][j]=valeur; } public void transposer(){ for(int j=i+1;j<n;j++){ (à suivre)‏ (suite)‏ int t=m[i][j]; m[i][j]=m[j][i]; m[j][i]=t; } //end for(int j… } //end transposer }

171 On obtient : $java SymMatrice 12 12 12
public class SymMatrice extends AbstractMatrice{ SymMatrice(int n){ super(n);} SymMatrice(int n, int x){ super(n,x);} public Matrice add(Matrice a) throws UnsupportedOperationException { if (! (a instanceof SymMatrice)) throw new UnsupportedOperationException(); int n=m.length; SymMatrice sa=(SymMatrice) a; Matrice r=new SymMatrice(n); for(int i=0;i<n;i++)‏ for(int j=0;j<n;j++)‏ r.setAt(i,j,m[i][j]+sa.m[i][j]); return r; } public void setAT(int i, int j, int valeur){ m[i][j]=m[j][i]=valeur;} public void transposer(){} public static void main(Strings[] args){ ... (à suivre)‏ (suite)‏ Matrice a=new SymMatrice(3,12); System.out.print(a); Matrice b=new SymMatrice(3); b.setAt(1,2,4); System.out.print(b); Matrice c=b.add(b); System.out.print(c); } On obtient : $java SymMatrice 0 0 0 0 0 4 0 4 0 0 0 8 0 8 0

172 On obtient : $java TestMap 1 2 3 4 5 6 7 8 9 10
Autre exemple : application d ’une méthode à tous les éléments d ’un conteneur / passage d’une interface en paramètre (à défaut de pouvoir passer une fonction en paramètre). On encapsule une méthode dans une interface : interface Function{ int applyIt(int n);} On encapsule la fonction mapcar dans une autre interface : interface Map{ void map(Function f);} Une classe qui peut réaliser un map inplémente cette interface : class Tableau implements Map{ int[] a; Tableau(int n){ a=new int[n]; for(int i=0; i<a.length;i++)‏ a[i]=i+1; } public void map(Function f){ a[i]=f.applyIt(a[i]); public String toString(){...} Un exemple de fonction: class Carre implements Function{ public int applyIt(int n){ return n*n;} } Un exemple d ’utilisation : public class TestMap{ public static void main(String[] args){ Tableau t=new Tableau(10); Function square = new Carre(); System.out.print(t); t.map(square); On obtient : $java TestMap

173 Info Notes prises par Amandine Revel et Christophe Vouaux

174 Exceptions Voici une classe pile, implémentée par un tableau
public class Pile{ private static final int maxP=4; private int hauteur=0; private int[] contenu=new int[maxP]; public boolean isEmpty(){ return (this.hauteur==0);} public boolean isFull(){ return (this.hauteur==maxP);} public void push(int x){ this.contenu[this.hauteur++]=x;} public int top(){ return (this.contenu[this.hauteur-1]);} public void pop(){ this.hauteur--; }

175 Il y a débordement lorsque l ’on fait :
top pour une pile vide; pop pour une pile vide; push pour une pile pleine. Une pile ne peut pas proposer de solution en cas de débordement, mais elle doit signaler (et interdire) le débordement. Cela peut se faire par des conditionnels, des assert(), ou bien encore par des exceptions. Une exception est un objet d’une classe qui étend la classe Exception. La classe Exception dérive de Throwable. La classe Throwable a une autre classe dérivée, la classe Error. Pour les piles on peut définir class PileException extends Exception{} En cas de débordement, on lève une exception, par l ’instruction throw. On doit signaler la possible levée d ’une exception au cours de l’exécution d ’une instruction d ’une méthode en signalant cette possible levée au niveau de la déclaration de cette méthode. Par exemple : void push(int x) throws PileException{ if this.isFull() throw new PileException(« Pile pleine »); this.contenu[this.hauteur++]=x; } L ’effet de la levée est : la propagation d ’un objet d ’une classe d ’exceptions qui est en général créé par new; la sortie immédiate de la méthode; la remontée dans l‘arbre d ’appel à la recherche d ’une méthode qui capture l ’exception.

176 La capture se fait par un bloc try / catch. Par exemple
Pile p=new Pile(); try { System.out.println(«top = »+p.top()); } catch (PileException e) { System.out.println(e.getMessage()); } Le bloc try lance une exécution contrôlée. En cas de levée d ’exception dans le bloc try, ce bloc est quitté immédiatement, et l ’exécution se poursuit par le bloc catch. Le bloc catch reçoit en argument l ’objet créé lors de la levée d’exception. Plusieurs catch sont possibles, et le premier dont l ’argument est du bon type est exécuté (à la manière d ’un case au sein d ’un switch). Les instructions du bloc finally sont exécutées dans tous les cas. try {…} catch {Type1Exception e) { … } catch {Type2Exception e) { … } catch {Exception e) { … } // cas par défaut, capture les exceptions non // traitées plus haut finally { … } // toujours exécuté

177 Exemple : try {…} catch {Exception e) { … } catch {PileException e) { … } // jamais exécuté Une levée d ’exception se produit lors d ’un appel à throw ou d ’une méthode ayant levé une exception. Ainsi l ’appel à une méthode pouvant lever une exception doit : ou bien être contenu dans un bloc try / catch pour capturer l ’exception ; ou bien être dans une méthode propageant cette classe d ’exception (avec throws). Les exceptions de la classe RuntimeException n ’ont pas à être capturées. Voici une interface de pile d ’entiers, et deux implémentations. Interface Pile{ boolean isEmpty(); boolean isFull(); void push(int x) throws PileException; int top() throws PileException; void pop() throws PileException; } class PileException extends Exception{ PileException(String s){super(s);}

178 Prise de notes promo 2008-2009 Rapporteur CM6 :
1 = Kevin Gauthier Yann Delcroix Lire la partie exception comment définir, comment lever, comment l’attraper/l’intercepter Le design pattern map a été écarté pour le moment …

179 Implémentation par tableau
public class ArrayPile implements Pile{ static final int maxP=4; private int hauteur=0; private int[] contenu=new int[maxP]; public boolean isEmpty(){ return (this.hauteur==0);} public boolean isFull(){ return (this.hauteur==maxP);} public void push(int x) throws PileException{ if isFull() throw new PileException(« Pile pleine »); this.contenu[this.hauteur++]=x;} public int top() throws PileException{ if this.isEmpty() throw new PileException(« Pile vide »); return this.contenu[this.hauteur-1];} public void pop() throws PileException{ this.hauteur--; }

180 Implémentation par liste (classe interne liste et empilement par appel du constructeur)‏
public class ListPile implements Pile{ private List tete = NULL; class List{ int cont; List suiv; List(int c, List s) { this.cont=c; this.suiv=s;} } public boolean isEmpty(){ return (this.tete==NULL);} public boolean isFull(){ return false;} public void push(int x) throws PileException{ this.tete=new List(x, this.tete);} public int top() throws PileException{ if this.isEmpty() throw new PileException(« Pile vide »); return this.tete.cont;} public void pop() throws PileException{ this.tete=this.tete.suiv;

181 Usage: public class TestPile { public static void main(String[] args){
Pile p=new ArrayPile(); // par table try{ p.push(2);p.pop(); p.pop(); // erreur -> exception levée p.pop(); // jamais atteint ! } catch (PileException e) { System.out.println(e.getMessage()); e.printStackTrace(); } Pile q=new ListPile(); // par liste q.push(2); q.push(5); q.pop(); q.pop(); System.out.println(q.top()); // erreur -> exception levée

182 Info Prise de note effectuée par …Cyril Michaud

183 Pattern de création : les fabriques
Une fabrique est une classe dont les méthodes ont en charge la construction d ’objets d ’une autre classe. Réalisation : une méthode chose createChose() {return new Chose();} Exemple, on cherche une méthode testVersion() qui permet de remplacer le corps de la méthode main de l ’exemple précédent par deux appels. En voici quelques variantes. public static void testVersion1(Pile p){ try{ p.push(2);p.push(5); p.pop(); p.pop(); System.out.println(p.top()); } catch (PileException e) { System.out.println(e.getMessage()); e.printStackTrace(); } Utilisé avec testVersion1(new ArrayPile()); testVersion1(new ListPile());

184 On peut délocaliser la création en une méthode de fabrique :
Si l ’on veut créer des choses, non pas au moment de l’appel, mais à l ’intérieur de la méthode de test : public static void testVersion2(boolean version){ Pile p; if version p=new ArrayPile(); else p=new ListPile; } Utilisé avec testVersion2(true); testVersion2(false); On peut délocaliser la création en une méthode de fabrique : public static void testVersion3(boolean version){ Pile p=createPile(version); testVersion3(true); testVersion3(false); On peut enfin transmettre un descripteur de classe : ...

185 On peut enfin transmettre un descripteur de classe :
public static void testVersion4(Class classPile) throws IllegalAccessException, instanciationException { Pile p; p=(Pile) classPile.newInstance(); } La méthode newInstance de la classe Class est une méthode de fabrique. On utilise cette méthode avec try { testVersion4(ArrayPile.class); testVersion4(ListPile.class); } catch(IllegalAccessException e){} catch(InstanciationException e){} catch(ClassNotFoundException e){}

186 Paquetages Le paquetage (package) est un mécanisme de groupement de classes. Les classes d’un paquetage sont dans un même répertoire décrit par le nom du paquetage. Le nom est relatif aux répertoires de la variable d’environnement CLASSPATH. Les noms de paquetage sont en minuscule. Par exemple, le paquetage java.awt.event se trouve dans le répertoire $(CLASSPATH)/java/awt/event (les classes java sont zippées dans les archives). Importer java.awt.event.* signifie que l’on peut nommer les classes dans ce répertoire par leur nom local, à la place du nom absolu. Cela ne concerne que les fichiers .class et non les répertoires contenus dans ce répertoire. Exemple: class MonAplette extends Applet // non trouvée class MonAplette extends java.applet.Applet // ok import java.applet.Applet; class MonAplette extends Applet // ok import java.applet.*;

187 Pour faire son propre paquetage, on ajoute la ligne
package nomrepertoire; en début de chaque fichier java qui fait partie de ce package. Le fichier .java doit se trouver dans un répertoire ayant pour nom nomrepertoire. Par défaut, le paquetage est sans nom (unnamed), et correspond au répertoire courant. Si une même classe apparaît dans 2 paquetages importés globalement, la classe utilisée doit être importée explicitement. Visibilité et paquetages Une classe ou une interface qui est déclarée public est accessible en dehors du paquetage. Si elle n’est pas déclarée public, elle est accessible à l’intérieur du même paquetage, mais cachée en dehors. => il faut donc déclarer publiques les classes utilisées par les clients utilisant le paquetage et cacher les classes donnant les détails d’implémentation. Ainsi, quand on change l’implémentation, les clients ne sont pas concernés par les changements puisqu’ils n’y ont pas accès.

188 Résumé concernant les paquetages
Un package est un fichier regroupant des classes. Pour créer un tel package, il suffit de commencer le fichier source contenant les classes à regrouper par l'instruction package suivi du nom que l'on désire donner au package. Toutes les classes contenues dans le fichier feront partie du package. Les package servent à structurer l'ensemble des classes et interfaces. Leur utilité est multiple : 1. Ils facilitent la recherche de l'emplacement physique des classes quand elles sont nécessaires (pour la compilation d'un fichier ou pour l'exécution d'un programme) ; 2. Ils rendent très improbable qu'il y ait confusion entre des classes de même nom ; 3. Ils structurent l'ensemble des classes selon une arborescence, ce qui rend beaucoup plus lisible l'ensemble ; Ils permettent de nuancer des niveaux de visibilité entre les classes selon qu'elles appartiennent ou non à un même paquetage. Les noms de paquetage prennent une forme telle que « MonPuzzle.MonPaquet ». Si la classe « MaPiece » se trouve dans un paquetage « MonPuzzle.MonPaquet », alors son nom complet est « MonPuzzle.MonPaquet.MaPiece ». Le fichier « MaPiece.class » sera nécessairement rangé dans le répertoire « MonPaquet » contenu dans le répertoire « MonPuzzle ». Autrement dit, la fin du chemin d'accès à ce fichier sera « MonPuzzle/MonPaquet ».

189 Programmation des listes
Une liste est une suite d ’objets. Comme séquence (a1, … an), elle se programme itérativement. (déjà vu)‏ Comme structure imbriquée (a1, (a2, (… (an, ()) … )), elle se définit récursivement. Une liste récursive se définit comme suit. Une liste est alors : soit une liste vide ; soit un cons d’un objet et d’une liste. A ce niveau il reste à concevoir la hiérarchie de classes puis déclarer les composants de ces classes (attributs, méthodes, visibilité, ...). La conception est orientée interface. Question subsidiaire : Comment concevoir une interface lorsque plusieurs sortes d’instance de classes sont utilisables ?

190 Programmation des listes
Ceci conduit à une interface pour les listes avec 3 interfaces, une pour le cons et une pour la liste vide, plus une interface qui déclare les méthodes communes. public interface Liste{ int length(); } public interface Cons extends Liste{ Object getElem(); void setElem(Object o); Liste getSuiv(); void setSuiv(Liste tail); public interface Nil extends Liste{};

191 L ’implémentation se fait naturellement :
Usage : public class TestListe{ public static void main(String[] args){ Liste l; l=new ConcreteCons(new Integer(1), new ConcreteCons(new Integer(2), new ConcreteNil())); System.out.println(«Liste de longueur»+ \ l.length()); } L ’implémentation se fait naturellement : public class ConcreteCons implements cons{ private Object o; private Liste suiv; public ConcreteCons(Object o, Liste suiv) { this.o=o; this.suiv=suiv; } public Object getElem(){ return o;} public void setElem(Object o){ this.o=o; } public Liste getSuiv(){ return this.suiv;} public void setSuiv(Liste suiv){ this.suiv=suiv;} public int length(){ return this.suiv.length()+1;} public class ConcreteNil implements Nil{ return 0;} Plusieurs appels à ConcreteNil() créent des liste nulles différentes. Pour éviter cela, on modifie : public class ConcreteNil implements Nil{ private static Liste nulle=new ConcreteNil(); private ConcreteNil(){} public static Liste getNil(){ return nulle;} public int length(){ return 0;} } Avec : l=newConcreteCons(new Ineger(1), new ConcreteCons(new Integer(2, ConcreteNil.getNil()));

192 Pattern de création : singleton
Une classe singleton est une classe qui ne peut avoir qu’une seule instance. Réalisation : un attribut privé statique instance désignant l’instance; une méthode publique de création qui teste si l’instance existe déjà; un constructeur privé. Exemple : public class ConcreteNil implements Nil{ private static ConcreteNil instance = null; private ConcreteNil(){} public static Liste getNil(){ if (instance==null) instance=new ConcreteNil(); return instance; } public int length(){ return 0;} Un singleton sert donc à contrôler le nombre d'instances d'une classe présent à un moment donné. Le but de ce design pattern est d’assurer au développeur une seule et unique instance d’une classe au sein de l’application. Ce qui signifie que lorsque l’on accède à une instance d’une classe équipée d’un singleton, on accède toujours à la même instance.

193 Prise de note promo 08-09 R1 = Guillaume Harel R2 = Nicolas Beaumont
Travail personnel = lire depuis la section package jusqu’à la partie singleton (design pattern)‏

194 Partie IV Java et les classes Fondamentales

195 4. Les classes fondamentales
1- Présentation des API 2- Les enveloppes des types de base 3- La classe java.lang.Object, mère de toutes les classes 4- Les chaînes de caractères 5- Ensembles structurés, itérateurs et comparateurs 6- Introspection

196 4.1 Les API Les API (Application Programming Interface) forment l’interface de programmation, c’est-à-dire l’ensemble des classes livrées avec Java. Les API (Application Programming Interface) standards de Java constituent un paquetage nommé java. Ce paquetage contient les sous paquetages suivants : Java.lang classes de base du langage java.io entrées/sorties java.util ensemble d ’outils : les classes très « utiles » java.net classes réseaux java.applet classes pour les appliquettes java.awt interfaces graphiques (Abstract Windowing Toolkit)‏ … et de nombreuses autres

197 Les enveloppes des types de base
boolean java.lang.Boolean char java.lang.Character byte java.lang.Byte short java.lang.Short int java.lang.Integer long java.lang.Long float java.lang.Float double java.lang.Double Une instance de la classe enveloppe encapsule une valeur du type de base correspondant. Chaque classe enveloppe possède des méthodes pour extraire la valeur d’un objet. Par exemple intValue() renvoie un int. Les noms varient d’une classe à l’autre. Un objet enveloppant est immutable : mais la valeur contenue peut-être modifiée. (c ’est-à-dire qu’un objet de type boolean restera toujours du même type mais la valeur contenue pourra être modifiée et issue de la conversion d’un objet d ’un autre type)‏ Pour palier à cela, on exploite la hiérarchie d’interfaces et de classes. On transforme souvent une valeur en objet pour utiliser une méthode manipulant ces objets. Ainsi, la programmation objet rejoint la programmation à-la-actionScript ou à la javascript ou une variable peut changer de type. Mais le programmeur contrôle complètement ce qu’il manipule (du moins il est censé le faire).

198 Info Les notes du CM7 ont été prises par Aurélien Seguin

199

200 Le clonage Le clonage est la construction d’une copie d’un objet.
La classe Object contient une méthode Object clone(). Lorsque cette méthode est appelée sur un objet d’une classe qui implémente l’interface Cloneable, elle crée une copie de l’objet du même type. La copie est superficielle de l’objet : les attributs de l’objet sont alors recopiés. Lorsqu’elle est appelée sur un objet d’une classe qui n’implémente pas l’interface Clonable, elle lève l’exception CloneNotSupportedException. La classe Object n’implémente pas l’interface Cloneable Exemple 1/2 : public class Point implements Cloneable { private int x, y; public Point(int _x, int _y){ this.x=_x;this.y=_y; } public String toString(){ return this.x+«, »+this.y; } public static void main(String[] args) throws CloneNotSupportedException{ Point a=new Point(5,3); Point b=(Point) a.clone();//méthode clone() de Object b.x=a.x+1; System.out.println(a); //5, 3 System.out.println(b); //6, 3} }

201 Le clonage Exemple 2/2 : public class Point implements Cloneable {
public int x, y; public Point p; public Point(int _x, int _y){ this.x=_x;this.y=_y; } public Point(int _x, int _y, Point _p){ this.x=x; this.y=y; this.p=_p} public String toString(){ return « Premier niveau ok : \t » + this.x+«, »+this.y « \n Deuxième niveau pas cloné : \t »+this.p.x;+«, »+this.p.y } public static void main(String[] args) throws CloneNotSupportedException{ Point a=new Point(3,5,new Point(1,1)); Point b=(Point) a.clone();//méthode clone() de Object System.out.println(a); //Premier niveau ok : 3,5 //Deuxième niveau pas cloné : 1,1 b.x=a.x+1; b.p.x=a.p.x+1; System.out.println(a); //3, 5 2,1 System.out.println(b); //4, ,1 }

202 Si on veut une classe « clonable » et une classe dérivée « non clonable », la classe dérivée implémente Cloneable mais on lève une exception dans l’écriture (de la surcharge) de clone(). Exemple de clonage Si le clonage par défaut est superficiel, celui-ci ne le sera pas en surchargeant la méthode clone() : public class Pile implements Cloneable { private int hauteur; private int[] contenu; public Pile(int maxP){ this.hauteur=0; this.contenu=new int[maxP];} public void push(int val){ this.contenu[hauteur++]=val;} public int pop(){ return this.contenu[this.hauteur--];} public Object clone(){ Pile nouvelObject=(Pile) super.clone(); nouvelObject.contenu=(int[])contenu.clone(); return nouvelObject; }

203 Public class TestPile{
public static void main(String[] args){ Pile f=new Pile(2); f.push(5); f.push(6); try { Pile g=(Pile) f.clone(); System.out.println(g.pop()); // 6 System.out.println(g.pop()); // 5 } catch (CloneNotSupportedException e) {} } Remarquer l ’utilisation de super.clone(), qui appelle clone() de Object, et qui crée toujours un objet du bon type. Si l’on souhaite clone un objet d’une classequi dérive d’autres classes, il convient de définir la surcharge de clone à chaque niveau. Sinon, l’appel à clone() sur un objet d’une classe dérivée de Pile serait incorrect. Si l’on n’est pas rigoureux, il faut alors faire appel à new Pile(). La 1ère méthode est la plus rigoureuse à-la-manière de toString(). Choisissons donc de redéfinir la fonction clone() pour la classe dérivée : Exemple public class DPile extends Pile{ private int cout; public DPile(int maxP){ super(maxP); this.cout=0;} public Object clone() throws CloneNotSupportedException{ DPile nouvelObject=(DPile) super.clone(); nouvelObject.cout=cout; return nouvelObject;

204 Egalité entre objets La methode equals() de la classe Object détermine si deux objets sont équivalents. Par défaut, deux objets sont équivalents s’ils sont accessibles par la même référence. Une classe peut redéfinir la méthode equals(). class Rectangle extends Forme{ private int largeur, hauteur; Rectangle(int l, int h){ this.largeur=l; this.hauteur=h; } public boolean equals(Object arg){ if (!(arg instanceof Rectangle) return false; Rectangle rarg=(Rectangle) arg; return ((this.largeur==rarg.largeur) && (this.hauteur==rarg.hauteur))} } Remarquer que l’argument est de type Object. Si l’argument était Rectangle, la méthode ne serait pas redéfinie mais surchargée. Elle serait alors ignorée lors d’un appel avec un argument de type Forme qui référence un Rectangle. La comparaison entre les 2 rectangles serait alors incorrecte.

205 Retour sur le clonage Copier un objet dont l’état peut changer ne se réduit pas à copier une référence vers cet objet. Les opérations suivantes doivent être effectuées: 1. Un nouvel objet doit être instancié, à partir de la même classe que celle de l’objet à copier; 2. Les variables d’instance de ce nouvel objet doivent prendre la même valeur que celles de l’objet à copier. Ces opérations portent le nom de clonage de l’objet. Exemple sous forme de graphique :

206 En langage Java, le clonage d’un objet s’effectue en lui envoyant le message clone(). Le résultat de cette opération est une référence de type Object, vers le clone crée. Afin de pouvoir être cloné, un objet doit donc posséder une méthode clone(). L’implémentation de celle-ci doit satisfaire aux critères suivants: • Le clonage superficiel de l’objet est réalisé par un appel à la méthode clone() de la classe Object. Cet appel peut être direct (pour des sous-classes directes de Object) ou indirect (via la méthode clone() de la classe parente); • Le clonage en profondeur s’effectue par des envois de messages clone() aux objets secondaires appropriés. Exemple avec une pile public class Stack implements Cloneable { private int nbElements; private Object[] contenu; ... public Object clone()‏ { Stack copie; try { copie = (Stack) super.clone(); copie.contenu = (Object[]) this.contenu.clone(); } catch (CloneNotSupportedException e)‏ { throw new InternalError("clonage impossible"); } return (Object) copie;

207 L'équivalence ou la méthode equals
La classe Object définit une méthode equals. Celle-ci peut être soit simplement héritée par d’autres classes, soit redéfinie. Par défaut, cette méthode effectue la comparaison la plus discriminante possible: Elle retourne true si et seulement si les références comparées désignent le même objet. Lorsqu’une classe redéfinit la méthode equals, il est nécessaire qu’elle redéfinisse également la méthode hashCode de la classe Object, destinée à calculer une valeur de hachage entière associée à l’objet courant. Cette méthode peut être implémentée librement, `a condition de satisfaire la contrainte suivante: Pour tous x et y tels que x.equals(y) retourne true, les valeurs calculées par x.hashCode() et y.hashCode() doivent être égales.

208 Les chaînes de caractères
La classe java.lang.String : la classe String est Final (c’est-à-dire qu’elle ne peut pas être dérivée). Elle utilise un tableau de caractères qui est un membre privé de la classe. Un objet de la classe String ne peut-être modifié. (On doit créer un nouvel objet). String nom=«toto»+ «tata»; System.out.println(nom.length()); // 8 System.out.println(nom.charAt(2)); // t CharAt Renvoie le caractère à la position spécifiée par le paramètre index. Si index n'est pas un nombre compris entre 0 et string.length - 1, une chaîne vide est renvoyée. Cette méthode est similaire à String.charCodeAt() sauf que la valeur renvoyée est un caractère, et non pas un code de caractère d'entier 16 bits. On peut construire un objet String à partir d’un tableau de caractères : char [] tableau={‘t’,‘o’,‘t’,‘o’}; String s=new String(tableau); et inversement : char[] tableau=«toto».toCharArray(); Conversion d’un entier en chaîne de caractères : String un=String.valueOf(1); //méthode statique qui appelle toString()‏ int i=Integer.valueOf(«12»).intValue(); // ou bien int i=Integer.parseInt(«12»); Comparaison des chaînes de caractères : on doit utiliser la méthode equals()‏ String s=«toto»; String t=«toto»; if (s.equals(t)) … // true

209 La classe java.lang.StringBuffer
La méthode compareTo() est l ’équivalent du strcmp() du C. La méthode trim() supprime tous les espaces blancs : String s=« toto  »; s=s.trim; // s=« toto » La classe java.lang.StringBuffer permet de créer des buffers de caractères de taille extensible. StringBuffer sb=new StringBuffer(« le »); sb.append(«  petit »); sb.append(« prince »); On récupère un String à partir d’un StringBuffer (sans recopie) : String mot=sb.toString; Ces classes sont sécurisées au niveau des thread (cf. plus tard). La classe java.util.StringTokenizer permet d’effectuer de l’analyse lexicale simple. String texte=«Le petit prince»; StringTokenizer st=new StringTokenizer(texte); while (st.hasMoreTokens()) { String mot=st.nextTokens(); // à rajouter un traitement sur “Le” } La classe StringTokenizer implémente l’interface java.util.Enumeration. Les délimiteurs par défaut sont les espaces, les retours chariots et les tabulations. On peut spécifier les délimiteurs : String texte=«http://lifc.univ-fcomte.fr/~canalda»; StringTokenizer st=new StringTokenizer(texte,«/:~»); if (st.countTokens()<=2) … // mauvaise url String protocole=st.nextToken(); String host=st.nextToken(); String login=st.nextToken();

210 Résumé sur les chaînes de caractères
Il existe beaucoup de fonctions associées aux chaînes de caractères pour faire des traitements sur celles-ci. Pour en avoir connaissance, il suffit d'aller dans la classe pour voir l'étendu des fonctions existantes (environ 40 fonctions de manipulation de chaînes). Parmi ces nombreuses fonctions, nous avons déjà abordé le StringBuffer pour la surcharge de ToString. Le StringBuffer permet de gérer des chaînes de caractères de taille illimitée (fichier temporaire). Comment utiliser le StringBuffer ? ✗ Il faut l’initialiser ✗ Constructeur qui prend le début du mot par exemple « le » ✗ On ajoute des informations grâce à la méthode append() StringTokenizer : permet de faire une analyse lexicale On désire analyser le string, pour cela on construit le StringTokenizer pour pouvoir faire le traitement adéquat. Quand on utilise le constructeur, un itérateur va se positionner en début de phrase et va permettre de l'organiser. Le hasMoreToken va répondre vrai à l'interrogation 'Il y a t il encore des éléments?' Si un element est encore présent, nextTokens permet de traverser le tocken actuel, de renvoyer le tocken actuel pour l'affectation à une variable et de se positionner sur le prochain token. La valeur actuelle peut être dans ce cas traitée. Ceci ainsi de suite jusqu'à la fin de la chaîne. HasMoreToken et nextTokens suffisent à voyager dans la chaine. La classe StringTokenizer les implémente. On peut spécifier des délimiteurs particuliers (comme //, ., etc.). Ainsi on peut l'appliquer à une multitude d'analyse. (exemple : analyse de l'adresse mail d'une personne)

211 TP 8 Groupe A Lundi 1 Décembre 2008 1er Rapporteur : Akram SALEM 2eme Rapporteur : Maxime CHEVASSON
Programme de la séance: 1. Avancement des projets 2. Explication de la partie réseau 

212 1. Avancement des projets
Durant cette séance, Mr Canalda a suivi l’avancement des projets dans toutes ces versions (texte Mono Poste-Mono Joueur, texte Mono Poste Multi Joueur, texte Multi Joueur Multi Poste, le diagramme de classe, Applet, frame …). Comme résultat de l’avancement des projets, on a abouti que la moyenne d’avancement des projets est a 90%, donc la majorité des groupes ont presque fini la première version du jeu. On voit ca plus détaillé dans les tableaux suivants :

213

214 Remarque : Chaque groupe doit rendre une version Applet et une version Frame. Rendu de la version finale 14 janvier grand maximum

215 2. Explication de la partie réseau
1) Initialisation : - création des instances des classes du Serveur. - gestion des clients - référence exos du cours qui traite de l’envoi de message à 1 utilisateur et à tous les utilisateurs. Schéma :

216 Code de base pour l’envoi du message de client vers serveur
//Instance de socket qui ouvre un port de communication Datagram Socket socket = new Datagram Socket(); while(true)‏ { //Création de variable de type byte « Octet » qui a la même longueur du message byte[] donnee = new byte[message. length()]; //Enregistrement du message sous forme des Bytes dans la variable donnee message.getBytes(0,message.length(),donnee,0); //Création d’une variable de type InetAddress “IP ADDRESS” et mettre dedans l’adresse //du serveur InetAddress dist=InetAddress.getByName(serveur); //Préparation des données pour l’envoi en les mettant dans un daragramPacket qui vont //en indiquant l’adresse du serveur et le port de l’envoi DatagramPacket dg = new DatagramPacket(donnee,donnee.length,dist,port); //envoi du DatagramPochet socket.send(dg); } //fermeture du socket socket.close();

217 2) Déroulement du jeu jeu = distribution de l’information pour le déroulement du jeu = informations liées aux états. (Diagramme état transition). En attente des connections des n joueurs, j’en ai 1, je les ai tous, début du jeu. [Puzzle rôle], récupération de l’action de Ci – on ne vérifie si pas faute par Cj – si oui on transmet à Cj – si non on transmet à Ci ; pas marqué les points.

218 Code de base pour la réception du message dans la partie serveur
private String text=new String(); //Instance de socket qui ouvre un port de communication public DatagramSocket socket; //Création d’une fonction qui va retourner le message envoyé public String Reception(){ //Creation d’un espace mémoire tampon vide pour recevoir le message sous forme « byte » byte[]tampon = new byte[2000]; try { while(true){ //ouverture du socket et lance l’écoute sur le port 1024 socket= new DatagramSocket(1024); //Création d’une variable datagramPacket de même taille qui la zone tampon DatagramPacket dg = new DatagramPacket(tampon,tampon.length); //Mise des données reçu par le socket dans la datagramSocket socket.receive(dg); //Conversion des données de Datagramsocket en STRING text = new String(dg.getData(),0,0,dg.getLength()); } //fermeture du socket socket.close(); catch(SocketException e )‏ System.err.println ("Le serveur existe déjà ! " + e);; catch(IOException e)‏ System.err.println( e);; //Retourne le texte reçu return text;

219 Remarque : Les mêmes fonctions de réception et de l’envoi sont presque pareil pour le client et le serveur Cette dernière étape se refait jusqu'à la résolution de tous le PUZZLE. 3) Fin du jeu Fin du jeu = qui à terminé le premier ? > Fin du programme et tout (déconnexion de tous les clients). Version autant multi thread qu’en réseau. Le Serveur qui crée 2 clients thread et chaque Client partage l’info sur le thread parent (le serveur).

220 TP 8 Groupe B Lundi 1 Décembre 2008 1er Rapporteur : Yoann DONIZETTI 2eme Rapporteur : Jules EID
Programme de la séance: 1. Appel 2. Animation collective mais avec l'appui d'un animateur

221 Objectif : L’objectif du cours est la continuité du TP7. Pour plus d’informations, lire le compte rendu correspondant. Le point le plus important était de savoir ou en était l’achèvement de la version texte du jeu pour la version un joueur monoposte. Cette mise au point a permis de voir ce qui posait problème comme par exemple pour le groupe « THE WIND UP » qui avait des difficultés concernant les threads et les exceptions. Ensuite, les points suivants ont été énoncés : o L’avancement du diagramme de classe pour la version monoposte mono joueur o L’avancement de la version texte avancée du jeu (multijoueur)‏ o L’avancement au niveau du Frame et de L’applet. o Savoir ou en est l’interface graphique o L’avancement du travail personnel Une présentation des groupes précédents a été faite : Le groupe Amertume a la version texte a 60% Les autres groupes sont au moins a 80%. Bien qu’il soit en retard en version texte, le diagramme de classe est fini à 100.% (voir compte rendu du groupe A TP 8). Le reste des groupes ont pratiquement finis leurs versions textes et les diagrammes de classe.

222 Les différents attentes du TP: ressemble a une check‐list qui devient de plus en plus précise. Sur celle‐ci , figure le rendu nécessaire pour avoir 20/20 : ‐ Version monojoueur version texte ‐ Diagramme de classe dans lequel il faut integrer les interfaces et l’emplacement des exceptions ‐ Les frames qui appele des champs textes, puis la version applet. ‐ Elaboration d’un diagramme de classe avancée. SI la version multi joueur est faite, celle‐ci est considérée comme bonus. Si on veut placer des Threads, il faut signaler ou ceux‐ci seront. ( il y a peu de différence entre thread et réseau).

223

224 Travail Personnel Explication pour les chronomètres Conclusion :
L’avancement du travail personnel permet de savoir qui sont ceux en déficit. Ce travail personnel auquel on rajouterait la conception et les exceptions permettent d’être au point pour l’examen final. Il reste essentiellement les thread et les listes. Explication pour les chronomètres Le Timer peut être un thread avec une exception. C’est une manière assez élégante d’intégrer le thread. L’intérêt du Timer est de pouvoir l’interrompre et le reprendre. Conclusion : THE WIND UP sont un tout petit peu en retard du fait que leur version texte est assez compliqué. Par rapport au groupe de TP A, les groupes B et C sont légèrement en retard. Certaines personnes ont du retard niveau travail personnel.

225 TP 8 Groupe C Lundi 1 Décembre 2008 1er Rapporteur : Aki IMADA 2eme Rapporteur : Sisalio PHENE
Programme de la séance: 1. Appel 2. Avancement des projets/Tour de table

226 Introduction Ce document est un compte rendu du TP n° 8 du 01 décembre 2008 dans le cadre du module « Conception et Développement pour le multimédia ». L’objectif de ce TP étant d’affiner le travail de la séance précédente afin de finaliser la première version texte mono-joueur mono-poste du jeu Puzzle. Le TP a commencé par l’appel, et ensuite nous avons réalisé une animation collective appuyée par le rapporteur 2 ( Sisalio P ), ce qui permet de savoir exactement l’avancement du travail de chaque groupe. Ordre du jour : Appel Animation collective dirigée par un animateur (rapporteur 2 → Sisalio)‏ Objectifs :continuité du TP7 1.Version texte α : 1-J, 1-P, 0-Thread 2.Diagramme de classes α avec l’interface et l’ (ou les )exception(s) : s’il y en a, préciser où. 3. Version texte β : n-J, 1-P, 0-Thread 4. Version texte β’ : n-J, 1-P, 1-Thread : s’il y en a, préciser où. 5. Frame + version texte α, β ou β’ 6. Applet + version texte α, β ou β’ 7. Diagramme de classes : où on est dans l’ensemble ? 8. Version graphique : détailler9. Travail personnel Les numéros orange en gras sont les indications importantes et obligatoires qui comptent pour la note sur 20. Dans d’autres groupes de TP, certains ont déjè fait la version graphique et ont éffectué le test (est-ce que les boutons marchent lorsque l’on appuie sur etc...)‏ Pour le travail personnel, on cherche à identifier plutôt ceux qui ne l'ont pas fait, ceux qui n’y arrivent pas, qui ne veulent plus. Cela permet de savoir exactement où on est, comment les aider, comment organiser le travail dans chacun des groupes.

227 « Warning 1 : Philippe M, Pierre Emmanuel R, Sisalio P »
% - Il manque la liste des pièces et la corbeille : se focaliser d’abord sur la liste, on peut ajouter la corbeille plus tard. → En fait, le debugage de liste des piéces : FINI 2. Pour le moment, pas d’interface. L’exception est en développement : à intégrer dans la classe Joueur. 3. La sélection Piece 4. NON Frame et Applet sont faits, mais ils ne sont pas encore intégrés dans la version α. 5. 6. 7. Rien de nouveau par rapport à la semaine dernière 8. Pas de version graphique pour le moment 9. Philippe M : Eclipse Pierre Emmanuel R : exercices de cours Sisalio P : debugage Le travail personnel est très bien réparti au sein de l’équipe et ils ont 2 semaines d’avance. Très bonne préparation pour l’examen final.

228 « Warning 2 : Benoit D, Aurélie M, Olivier M, Aurélie T »
% 2. Ils ont commencé la classe interface et l’exception est en développement : à intégrer dans la classe Puzzle. 3. NON 4. NON Frame et Applet sont en développement : à intégrer. 5. 6. 7. Il reste à ajouter des fonctions et à intégrer la classe test. 8. Le design est fait, mais il n’est pas intégrer ni tester. 9. Benoît D : Keyboard, Jeu fonction appel Aurélie M : exercices de cours, classe test, matrices Olivier M : ? Aurélie T : ? Au niveau du travail personnel, ils sont aussi équilibrés que Warning1. S’ils continuent comme cela, il n’y aurait pas de problème pour l’examen final.

229 « i-travel : Olivier V, Pierre Damien T, AKi I, Guillaume V, Anaïs A »
% - Il reste à améliorer les codes concernant la PieceBonus et la PieceMalus. 2. à remanier en fonction du code qui intègre une interface et à intégrer une exception (placement en dehors du plateau)‏ 3. NON 4. NON 5. Base : champs texte dans l’interieur d’Applet → OK 6. NON 7. Il n’y a pas de modification depuis la séance dernière. 8. La réalisation du gabaris dans cette séance. 9. Olivier V : voir compilation de classes tests Pierre Damien T : réflexion Aki I : exercices de cours, base de Frame et d’Applet Guillaume V : voir Applet Anaïs A : apprentissage exception Un petit peu en retard au niveau du travail personnel, notamment Olivier V et Pierre Damien T. Il faut essayer de coder et d’effectuer les classes test dans cette séance pour que les autres puissent les aider, sinon au plus tard dans la semaine.

230 Evolution dans le cours
i-travel a commencé à faire le gabaris sur Photoshop : on garde la même presentation graphique que dans le cahier des charges, sauf que l'écouteur du dessus qui faisait office de slider ne remplit plus cette fonction et devient un simple élément de décor dans la nouvelle version du cahier des charges. Il passe donc en bas du plateau. En code, le problème qu'on a évoqué la semaine dernière a été résolu. Maintenant, on est en train de améliorer les codes de PieceMalus et de PieceBonus. Info sur l’examen final Il y aura peu de code: un peu d’exercice comme nous avons vu en cours sur les codes Alpha, Beta et Gamma. Ce sera plus des questions sur la conception, la façon de structurer des codes. On peut intégrer des codes dans la réponse comme exemple pour l’illustrer, mais il faut bien évidemment que ce soit correct et justifié. Pour les explications que l’on met, c’est pareil, ne racontez pas n'importe quoi ! Toutes les notes de cours et/ou d'autres documents (si nécessaire) sont autorisés. Moyenne de l’examen sur table de l’an dernier = autour de 11, 12. Référence de Tutorial Java conseillé par Anaïs A : ftp://ftp-developpez.com/java/livres/javaEnfants/JavaEnfants.pdf

231 Info Anne-Sophie

232 Promo 2008-2009 Préparer le cours jusqu’à slide 182
Guillaume Lugand R1 Et Alexandre Teissier R2

233 Outils mathématiques On peut trouver des outils mathématiques dans les 2 classes et le paquetage qui suivent : java.lang.Math java.lang.Random java.math (pour le travail sur les entiers longs et sur les flottants) Exemple : int maximum=Math.max(3,4); Exemple : tirer au hasard un nombre entre 100 et 1000 (bornes comprises)‏ int maximum=100+(int) (Math.random()*900); Une instruction arithmétique sur les entiers peut lever l’exception ArithmeticException : try { int i=1/0; } catch (ArithmeticException e){...}; Une instruction arithmétique sur les flottants ne lève pas d’exception. Une expression flottante peut prendre 3 valeurs particulières : POSITIVE_INFINITY 1.0/0.0 NEGATIVE_INFINITY -1.0/0.0 NaN /0.0

234 .math est une classe pour les entiers long et les flottants.
Dans un langage quand on travaille avec des entiers de grande taille, les exceptions sont très couteuses en terme de traitement, on les trouvent dans le package .math Pour les maths il y a tout une abondance de fonctions correspondantes. Max Min par exemple. Ce type de test de maximum existe déjà pour les entiers et les flottants. Contrairement aux entiers, lorsque l'on fait des opérations avec les flottants, on peut diviser par 0. Dans ce cas, on obtiendra : ✗ soit une valeur infinie positive ✗ soit une valeur infinie négative Par contre lorsque l'on divise 0 par 0 on obtient « not a number »

235 Ensembles structurés, itérateurs, comparateurs
Collection Map List Set SortedMap ArrayList LinkedList Vector hashSet SortedSet Hashtable HashMap TreeMap TreeSet

236 Différences entre une liste et un ensemble : Un ensemble n’a qu’une seule occurrence de chaque objet, alors que dans une liste il peut y en avoir plusieurs. Dans la manipulation d’un ensemble, il y a donc unicité de l’objet. Si on veut rajouter un objet, la bibliothèque va vérifier que l'objet n'existe pas. S'il existe il ne va pas l'ajouter. Une liste par naissance est non ordonnée. Le mode d'insertion dans la liste va donner l'ordre (le classement). Par exemple, On peut faire une insertion en tête ou une en fin de liste.. Quand on insère en tête, la liste va pouvoir fonctionner comme une pile. Quand on insère à la fin, on retrouve la liste d'attente. Comme nous avons vu ci-dessus, dans un ensemble nous pouvons avoir des ensembles ordonnés et d'autres non ordonnés. Ainsi, si on veux travailler avec des objets ordonnés, il faut éviter de travailler avec les listes mais privilégier les ensembles. C'est le principe de base pour comprendre les catalogues.

237 Exemple : java.util.ArrayList : java.util.Iterator :

238 Grâce à javap nous pouvons voir que la classe ArrayList :
✗ est une classe public ✗ comporte une multitude d'implémentation d'interface, on retrouve l'interface List pour la manipulation des listes, un RandomAccess qui permet de manière aléatoire d'accéder à un élément de la liste. ✗ clonable : il est facile de cloner une liste. Cette commande donne le profil des fonctions disponibles pour une classe en question sans passer par la documentation lourde. Elle donne des informations concentrées de Javadoc (informations d'implémentation et d'extension). Quel sont les fonctions des ArrayList renvoyer par la commande javap ? Constructeurs, ArrayList qui prend une collection en paramètre. Il est possible de prendre un Treeset et de le transformer en ArrayList. On a un trimToSize, pour faire le tri d'un tableau (enlève les cases vides d'un tableau). Si un tableau de 100 cases utilise uniquement 4 cases, trimToSize du tableau en question ne tiendra compte que des 4 cases utilisées. (surtout utilisé sur les grands tableaux) Size permet de récupérer la taille de l'ArrayList. Contains permet de vérifier si un objet est présent dans la liste indexOf passe un objet en paramètre et vérifie si il est présent pour le retourner dans l'index. (s'il n'est pas présent, indexOf retourne -1) clonn : permet de cloner toArrayList : permet de transformer un ArrayList en tableau simple; get in : permet de récupérer un objet à une case déterminée. clear : permet de nettoyer addAll : ajoute une collection à un ArrayList existant à une case donnée. RemoveRange : enlève un élément d'un indice à un autre.

239 Vue d ’ensemble Deux interfaces :
Collection : pour les ensembles d’objet, Map pour les tables, c-à-d les ensembles de couples (clé, valeur), où la clé et la valeur sont des objets. Des itérateurs sur les collections : Iterator : interface des itérateurs, ListIterator : itérateur sur les séquences, Enumeration : ancienne forme des itérateurs. De plus, deux classes d’utilitaires Collections : avec algorithmes de tris, … Arrays : avec algorithmes spécialisés sur les tableaux. Les opérations principales sur une collection : add : pour ajouter un objet, remove : pour enlever un objet, contains : test d’appartenance, size : pour obtenir le nombre d’éléments, isEmpty : pour tester si l’ensemble est vide Comme les éléments sont des objets, ne pas écrire c.add(2) mais c.add(new Integer(2)).

240 Sous-interfaces spécialisées de Collection :
List spécifie les séquences, avec les méthodes int indexOf(Object o) position de o, Object get(int i) retourne l’objet à la position i, Object set(int i, Object o) remplace l’élément en position i, et retourne l’élément qui s ’y trouvait précédemment. Set spécifie les ensembles sans duplication, SortedSet sous-interface de Set pour les ensembles ordonnés: Object first() retourne le premier objet, Object last() retourne le dernier objet, SortedSet subset(Object initial, Object final) retourne une référence vers le sous- ensemble des objets >= initial et < final. Opérations ensemblistes sur les ensembles boolean containsAll(Collection c) : pour tester l’inclusion boolean addAll(Collection c) : pour la réunion boolean removeAll(Collection c) : pour la différence boolean retainAll(Collection c) : pour l’intersection Les 3 dernières méthodes retournent true si elles ont modifié la collection.

241 Retour sur les vues d’ensemble
Pour conclure, il est important de bien avoir en tête la partie Collection et Map. (respectivement ordonné et non ordonné) le Map va intégrer le hachage pour faire des rangements optimisés et intelligents. Le setter va remplacer quelque chose mais aussi en renvoyer la valeur, pour un traitement par exemple. Ranger des choses en choisissant un type ? Ceci n'est pas possible avec une liste. Avec une Map on peut le faire, avec une clé de hachage dans une même liste. Exemple : List : si on souhaite lister des hommes et des femmes avec List sans les mélanger, deux listes sont nécessaires. Femmes : Hommes : Map : avec Map, une seul et unique liste est nécessaire pour lister des hommes et des femmes. Les éléments hommes et femmes seront deux clés différentes. hommes & femmes :

242 Implémentation d’une collection
Pour les collections : ArrayList (recommandée, par tableau), et LinkedList (par liste doublement chaînée) implémentent List. Vector est une vieille classe (JDK 1.0) « relookée » qui implémente aussi List. Elle a des méthodes spécifiques. HashSet (recommandée) implémente Set, TreeSet implémente SortedSet. Le choix de l’implémentation résulte de l’efficacité recherchée : par exemple, l’accès indicé est un temps constant pour les ArrayList, l’insertion entre 2 éléments est un temps constant pour les LinkedList. Discipline d’abstraction : les attributs, paramètres, variables locales sont déclarés avec, comme type, une interface (List, Set)‏ les classes d’implémentation ne sont utilisées que par leur constructeurs. Exemple : List l=new ArrayList(); Set s=new HashSet();

243 Exemple : Programme qui détecte une répétition dans les chaînes de caractères d’une ligne. Import java.util.Set; import java.util.HashSet; class TestSet{ public static void main(String[] args){ set s=new HashSet(); for(int i=0; i<args.length;i++)‏ if !(s.add(args[i]))‏ System.out.println(«Déjà vu : » + args[i]); System.out.println(s.size()+« distincts : »+s); } $ java TestSet a b c a b d Déjà vu : a Déjà vu : b 4 distincts : d c b a

244 Itérateurs L ’interface Iterator définit les itérateurs.
Un itérateur permet de parcourir l’ensemble des éléments d’une collection. Java propose 2 schémas, l’interface Enumeration et l’interface Iterator. L ’interface java.util.Iterator a 3 méthodes : boolean hasNext() qui teste si le parcours contient encore des éléments; Object next() qui retourne l’élément suivant si un tel élément existe, (et lève une exception sinon); void remove() qui supprime le dernier élément retourné par next(). L ’interface java.util.Enumeration a 2 méthodes : boolean hasMoreElements() qui teste si l’énumération contient encore d’autres éléments ; Object nextElements() qui retourne l’élément suivant s’il existe (une exception sinon). Exemple : import java.util.*; public class Personne{ private String nom; private int age; public Personne(String nom, int age){this.nom=nom; this.age=age;} public String toString(){return «Nom: »+this.nom+«, age : »+this.age);} } class TestHashSet{ ...

245 On obtient : $java testHashSet Nom : Philippe, age : 38
class TestHashSet{ public static void printAll(Collection c){ for(Iterator i=c.iterator();i.hasNext();)‏ System.out.println(i.next()); } public static void main(String[] args){ Set s=new HashSet(); s.add(new Personne(«Philippe»,38)); s.add(new Personne(«Ines»,5)); s.add(new Personne(«Erwan»,2)); s.add(«Université»); s.add(«pu-pm»); printAll(s); Set t=(Set) ((HashSet) s).clone(); System.out.println(s.size()); printAll(t); Iterator i=t.iterator(); while (i.hasNext())‏ if (i.next() instanceof Personne) i.remove(); On obtient : $java testHashSet Nom : Philippe, age : 38 pu-pm Nom : Erwan, age : 2 Universite Nom : Ines, age : 5 5 Nom : Philippe, age : 38 Observez le désordre

246 Détails sur les itérateurs.
La méthode iterator() de la collection positionne l’itérateur au début, la méthode hasNext() teste si l’on peut progresser, la méthode next() avance d’un pas dans la collection, et retourne l’élément traversé, la méthode void remove() supprime l’élément référencé par next(), en conséquence de quoi il ne peut pas y avoir de remove() sans next()‏ |A B C iterator(), hasnext()=true A|B C next()=A, hasnext()=true A B|C next()=B, hasnext()=true A B C| next()=C, hasnext()=false Iterator i=c.iterator(); i.remove(); // non i.next(); i.remove(); // oui i.remove(); // non

247 Résumé sur les itérateurs
Un itérateur permet de parcourir l'ensemble des éléments d'une collection. Java propose 2 schémas, l'interface Enumeration et l'interface Iterator. Les méthodes de Enumeration : ✗ Boolean hasMoreELements() : test si l'énumération contient encore d'autre éléments. ✗ Object nextElement() : qui retourne l'élément suivant si il existe (dans le cas inverse une exception est levée) Les méthodes de Iterator : ✗ Boolean hasNext() : test si l'énumération contient encore d'autres éléments. ✗ Object next() : qui retourne l'élément suivant s'il existe (dans le cas inverse une exception est levée) ✗ void remove() : qui supprime le dernier élément retourné par next() Les itérateurs permettent de traiter des applications plus complexes. Cependant, même avec des applications complexes, il est possible de gagner énormément en terme de lignes de codes. Pour se faire il est nécessaire de réfléchir avec les ensembles.

248 Exemple de tableau On désire créer un tableau de références sur des objets de type Forme qui peuvent être Rectangle ou Ellipse. import java.util.ArrayList; import java.util.Iterator; public abstract class Forme{ public abstract double getAire(); // à définir public String toStringAire(){ return «Aire = »+getAire();} // commune } class Rectangle extends Forme {…}; class Ellipse extends Forme{…}; class TestForme{ public static void main(String[] args){ Forme r1=new Rectangle(6,10); Forme r2=new Rectangle(5,10); Forme e1=new Ellipse(3,5); List l=new ArrayList(); l.add(r1); l.add(r2); l.add(1,e1); // on obtient r1, e1, r2 for(Iterator it=l.iterator(); it.hasnext();)‏ System.out.println(((Forme) it.next()).toStringAire()); 1 2 3 n

249 Itérer sur les listes Les listes sont des séquences. Un itérateur de listes implémente l’interface ListIterator. Il a des méthodes supplémentaires : Object previous() qui permet de faire un parcours arrière (reculer); boolean hasPrevious qui retourne true s’il y a un élément qui précède; void add(Object) qui ajoute l’élément juste avant l’itérateur ; void set(Object o) qui substitue o à l’objet référencé par next(). Exemple : import java.util.*; class TestLinkedList{ public static void printAll(Collection c){ … } public static void main(String[] args){ List l=new LinkedList(); l.add(«A»);l.add(«B»);l.add(«C»); printAll(l); // A B C ListIterator itl=l.listIterator(); System.out.println(itl.next()); // A|B C -> A System.out.println(itl.hasPrevious()); // true System.out.println(itl.previous()); // | A B C -> A itl.add(«X»); printAll(l); // X | A B C }

250 Promo Début CM 10 GRASSWILL Julien R1 WOERLY Maxime R2

251 Comparaison On obtient : $java TestComparaison Anne 25 Paul 25 Paul 21
Java exprime que les objets d’une classe sont comparables si cette classe implémente l’interface Comparable. L’interface Comparable déclare une méthode int compareTo(Object o) telle que a.compareTo(b) est : négatif, si a < b nul, si a=b positif si a>b Exemple, la comparaison de « noms » : import java.util.*; class Nom implements Comparable{ private String nom; private int age; public Nom(String n, int a){ this.age=a; this.nom=n;} public int compareTo(Object o){ Nom n=(Nom) o; int comp=this.nom.compareTo(n.nom); return (comp!=0) ? comp : n.age - this.age;} // à nom égal le - âgé est supérieur } class TestComparaison{ public static void main(String[] args){ Collection c=new TreeSet(); c.add(new Nom(«Paul», 21));c.add(new Nom(«Paul», 25));c.add(new Nom(«Anne», 25)); for(Iterator it=c.iterator(); it.hasNext();)‏ System.out.println(it.next()); On obtient : $java TestComparaison Anne 25 Paul 25 Paul 21

252 Détails et explications sur la comparaison
Dans un premier temps pour utiliser les méthodes de Comparable(), il faut implémenter la classe Comparable « Implements comparable ». Dans la pratique, le comparateur permet de comparer 2 valeurs entres elles comme par exemple un « carré » et un « rectangle » pour vérifier les aires de chacun et les comparer. Cela marche d’une manière plus générale sur tous volumes ou objets de type entiers et flottants, mais pour les chaines de caractères il faut procéder différemment. Il y a un comparateur par défaut sur les chaines (exemple : Doupond sera inférieur à Doupont). On aura n>this et si l’âge est le même, il y a égalité parfaite. INFO : Veiller à commenter les comparateurs dans les applications pour aider à la compréhension. Explication de l’exemple de la comparaison de « noms »: La fonction compareTo(Object o) permet de comparer 2 valeurs de type Nom : Public int compareTo(Object o){ Nom n=(Nom) o ; Int comp=this.nom.compareTo(n.nom) ; Return (comp !=0) ? comp : n.age – this.age ; } Ici le transtypage de l’objet passé en paramètre est nécessaire afin d’être sur de comparer deux objets de même type Nom. Nom = (Nom) o ; La notion de transtypage pour les comparateurs est très importante afin de bien comparer les même types d’informations entre elles.

253 Pour comparer les chaines, on prend le courant (this
Pour comparer les chaines, on prend le courant (this.nom) et on le compare à n.nom. En langage Java cela se traduit par la ligne suivante : This.nom.compareTo(n.nom) La fonction enfin retourne le résultat de la comparaison. Si le nom est le même alors on test l’âge, le moins âgé sera supérieur. Return (comp !=0) ? comp : n.age – this.age ; //à nom égal le moins âgé est supérieur NOTE : Il faut surcharger la fonction compareTo(). Le comparateur va être utile pour la manipulation des listes(ou collections), on va pouvoir les trier simplement. L’exemple du cours illustre bien cette dernière phrase. Class TestComparaison{ Public static void main (String[] args){ Collection c=new TreeSet(); c.add(new Nom(“Paul”, 21); c.add(new Nom(“Paul”, 25); c.add(new Nom(“Anne”, 25); for(Iterator it=c.iterator(); it.hasNext();){ System.out.println(it.next()); } Ici le résultat est le trie par importance des noms. Paul 25 et Paul 21 sont égaux, on compare donc l’âge. Etant donné que le choix du test de comparaison vu précédemment voulait qu’à nom égal, le moins âgé est supérieur, en sortie on aura donc : Anne 25 Paul 25 Paul 21 NOTE : Détail sur les itérateurs : La méthode Iterator() de la collection positionne l’itérateur au début La méthode hasNext() teste si l’on peut progresser La méthode next() avance d’un pas dans la collection et retourne l’élément traversé

254 Comparateur Un comparateur est un objet qui permet la comparaison. En java, l’interface Comparator déclare une méthode int compare(Object a, Object b). On se sert d’un comparateur dans : un constructeur d’un ensemble ordonné; dans les algorithmes de tris fournis par Collections. Exemple, deux comparateurs de « noms » : import java.util.*; class NomComparator implements Comparator{ public int compare(Object oa, Object ob){ Nom a=(Nom) oa; Nom b=(Nom) ob; int comp=a.getNom().compareTo(b.getNom()); if (comp==0) comp=a.getAge()-b.getAge(); // à nom égal, le plus âgé est supérieur return comp; } class AgeComparator implements Comparator{ int comp=b.getAge()-a.getAge(); if (comp==0) comp=a.getNom().compareTo(b.getNom()); // à âge égal, l’ordre alphabétique return comp; // du nom fait la différence

255 Comparateur On obtient :
Une liste de noms pour pouvoir trier sans peine : public static void main(String[] args){ List c=new ArrayList(); c.add(new Nom(«Paul», 21));c.add(new Nom(«Paul», 25));c.add(new Nom(«Anne», 25)); printAll(c); Collections.sort(c,new NomComparator()); Collections.sort(c,new AgeComparator()); } On obtient : Anne : 25 Paul : 21 Paul : 25 // ordre sur Noms Anne : 25 Paul : 25 Paul : 21 // ordre sur Ages Paul : 21 Paul : 25 Anne : 25 // ordre d ’insertion

256 Résumé sur le comparateur
On se sert d’un comparateur dans un constructeur d’un ensemble ordonné et dans les algorithmes de tris fournis par Collections essentiellement. Grâce aux collections, on peut choisir un trie particulier qui va avoir un effet sur notre liste en fonction de l’ordre des comparaisons appelées. On peut par exemple créer dans un premier temps une nouvelle instance de NomComparator() ; et ensuite une instance de AgeComparator() ; List c=new ArrayList() ; Collections.sort(c, new NomComparator() ); //en sortie : Anne:25 Paul:21 Paul :25 Collections.sort(c, new AgeComparator() ); //en sortie : Anne:25 Paul:25 Paul :21 NOTE : Ce trie diffèrerait si l’on avait choisit d’instancier d’abord AgeComparator() ; puis NomComparator() ;

257 Tables Implémentation d’une table
L ’interface Map spécifie les tables, qui sont des ensembles de couples (clé, valeur). Les clés ne peuvent pas être dupliquées, et au plus une valeur est associée à une clé. Object put(Object key, Object value) insère l’association (Object key, Object value) dans la table et retourne l’object précédemment associé à la clé ou bien null ; boolean containsKey(Object key) retourne vrai s’il y a une valeur associée à cette clé ; Object get(Object key) retourne l’objet associé à la clé dans la table; Object remove(Object key) supprime l’association de clé key. Retourne l’objet précédemment associé. Retourne null si null était l’objet précédemment associé ou bien encore si key n’est pas une association de la table. La sous-interface SortedMap spécifie les tables dont l’ensemble des clés est ordonné. Implémentation d’une table Pour les tables : HashMap (recommandée) implémente Map ; HashTable est une vieille classe (jdk 1.0) qui implémente aussi Map. Elle a des méthodes personnelles ; TreeMap implémente SortedMap. La classe TreeMap implémente les opérations avec des arbres rouge-noir. Un TreeMap stocke les références de ces objets de telle sorte que les opérations s’exécutent en temps O(log(n)), pourvu que l’on définisse un bon ordre. Et c’est java.util.Comparator qui permet de spécifier un comparateur des clés.

258 Algorithme de tri Array est utilisé pour le tri de tableaux. Collection est la mère de toutes les classes de classement Dans toutes les classes, il existe les méthodes add(), remove(), containts(), size(), isEmpty() c.add manipule des entiers et non des objets donc on utilise c.add(new integer(2)) qui permet de traduire un objet en entier. Il y a des sous interfaces spécialisées de Collection comme indexOf, Set, addAll (prend les éléments pour les intégrer), removeAll (enlève tous les éléments présents dans les parenthèses dans la liste) et retainAll (récupère l'intersection de l'ensemble). Dans les animations il est très fréquent de penser avec les ensembles

259 Résumé sur les tables et l’algorithme de tri
Pour différentes valeurs, on peut avoir différentes clés mais chaque clé doit être différentes des autres, c'est‐à‐dire unique. Si une clé était déjà utilisée, le dernier put va écraser la valeur précédente. Il est donc important de souligner le faite que les éléments ne sont pas accessibles avec un index mais une clé. La notion d'ordre n'y est pas pertinente. Le type Map est une interface qui doit être implémenté par les classes. « SortedMap vous permet de spécifier les tables dont l’ensemble des clés est ordonné. » En effet, pour avoir un ordre, on peut utiliser SortedMap qui est implémenté par TreeMap. Les tables ordonnées sont des tables dont les éléments sont triés par ordre croissant. Le tri des éléments est basé sur un Comparator fourni comme argument lors de la création de la table ou dans le cas ou cet objet n'est pas fourni, sur la méthode compareTo() des éléments (qui doivent dans ce cas implémenter l'interface Comparable). Remarque sur la complexité logarithmique : D’ordinaire quand on fait un trie on met les éléments les uns après les autres puis on cherche à les trier. Exemple : AGE On parcourt une première fois pour trouver 12 Ensuite on parcourt à nouveau pour 13 (n‐1 élément) et ainsi de suite jusqu’à avoir trié tous les n éléments. Il y a donc n(n+1)/2 , c’est ce qu’on appelle la complexité du trie. Plus simplement, on voit enfaite que le nombre d’opérations est à peu près égal au nombre d’éléments car on re‐parcourt à chaque fois la liste pour trie un par un les n éléments. C’est ce qu’on appel une recherche dichotomique. En logarithmique, on cherche à trier en fonction des valeurs. Et donc en fonction des clés on va faire du stockage sous la forme d’un arbre. Par ce principe on organise de façon à ce que le nombre de test soit limité, en testant la valeur des clés. On limite ainsi le nombre d’opérations. Par ce procédé on parcourt simplement l’arbre de noeuds en noeuds puis on compare (si 6<13 alors on descend au noeud suivant et ainsi de suite jusqu’à se retrouver à l’endroit voulu).

260 Formes nommées R1 On obtient : $java FormeMapTest aire = 50.0 E1 R2
On associe un nom à chaque forme. Le nom est la clé de la forme. L’interface Forme, et les classes Rectangle et Ellipse restent inchangées. import java.util.*; public class FormeMapTest{ public static void main(String[] args){ Forme r2=new Rectangle(6,10); Forme r1=new Rectangle(5,10); Forme e1=new Ellipse(3,5); TreeMap arbrel=new TreeMap(); arbre1.put(«R2»,r2); arbre1.put(«R1»,r1); arbre1.put(«E1»,e1); System.out.println(((Forme) arbre1.get(«R1»)).toStringAire()); } On obtient : $java FormeMapTest aire = 50.0 E1 R1 R2

261 public java.util.TreeMap(java.util.Comparator); Le programme devient :
Si l’on désire trier les clés en ordre inverse, on change le comparateur. La classe java.util.TreeMap possède un constructeur qui permet de changer le comparateur : public java.util.TreeMap(java.util.Comparator); Le programme devient : import java.util.*; public class OppositeComparator implements Comparator{ public int compare(Object oa, Object ob){ return -((comparable) oa).compareTo(ob); //ordre inverse } Cette méthode lève une exception NullPointerException si oa est null. Le reste de la vérification est déléguée à compareTo. class TestForme{ public static void main(String[] args){ Forme r2=new Rectangle(6,10); Forme r1=new Rectangle(5,10); Forme e1=new Ellipse(3,5); Comparator c=new OppositeComparator(); TreeMap arbrel=new TreeMap(c); arbre.put(«R2»,r2); arbre.put(«R1»,r1); arbre.put(«E1»,e1); System.out.println(arbre.firstKey()+ « » + arbre.lastKey()); // «R2» «E1»

262 Retour sur les formes nommées
Pour afficher un ensemble il faut le parcourir. Tout d'abord on prend la collection en paramètre, on va parcourir n'importe quel objet avec l'itérateur de son choix. On crée un itérator (iterator ou enumeration), tant qu'il y a un next à l'iterator je le traverse et j'affiche l'élément traversé, on poursuit ainsi de suite. Précisions sur la méthode add() du HashSet : ✗ On peut cloner une liste en une seule ligne et il n'y a pas de problèmes de profondeur. ✗ On peut afficher la taille de l'ensemble avec system.out ✗ On peut afficher sa taille avec print. ✗ On peut faire un traitement dessus. Si on veux afficher tout les éléments en enlevant les personnes uniquement, il suffit d'associer un iterator sur la collection, tant que hasNext est vrai on parcourt le tableau en testant (avec un while par exemple) le type de la valeur instantanée. Si c'est une personne, on fait un remove sinon on l'affiche. A la fin du traitement, nous obtenons l'ensemble HashSet sans les personnes (l'ordre d'insertion n'est pas préservé).

263 TP 9 Groupe A Mercredi 3 Décembre er Rapporteur : Claire Mugnier 2eme Rapporteur : Déborah Lambert Déroulement de la séance - Appel - Remarque sur l’utilisation des threads - Tour de table Remarque sur l’utilisation des threads On fait tout d’abord une version sans threads et ensuite on les rajoute. On doit valider une version sans threads sinon c’est impossible à traiter.

264

265

266

267

268 TP 9 Groupe B 1er Rapporteur : Meriza Lenanda 2eme Rapporteur : Céline Cucherousset
PLAN DU COMPTE RENDU: I. DEROULEMENT DE LA SCEANCE Page 2 II. RAPPEL SUR LA VERSION RESEAU Pages 3, 4 et 5 III. TABLEAU RECAPITULATIF DE L’AVANCEE DES PROJETS Page 6

269

270 TP 9 Groupe C 1er Rapporteur : Olivier MOUROT 2eme Rapporteur : Aurélie MARATRAY
Appel Animation collective (Animatrice A. MARATRAY) Continuité des précédents TP

271

272

273

274 Explication relation client / serveur
Fonctionnement d’une relation Client/serveur pour le jeu JAVA U1 est prévenu des arrivants. U5 prévient U4 qu’il rejoint la partie et attend U6, U7…U10. Coté Serveur : Tout d’abord c’est la phase d’initialisation, de construction du jeu. Il attend ensuite la connexion du jeu. Une fois que le joueur est connecté et si le nombre prévu est atteint la connexion se fait et le jeu peut commencer. Le joueur 4/10 qui attend le nombre maximal peut voir qui est déjà connecté, leurs infos et leurs noms. Coté Client : On vérifie si les clients sont bien connectés. Lors du jeu, un joueur joue 1 pièce et les autres joueurs voient les informations du déplacement de la pièce. Différence entre le jeu THREAD et le jeu RESEAU : Il s’agit de la même logique, cependant le jeu THREAD agit directement sur le jeu tandis que le RESEAU passe par un socket. Question posée à la suite de l’explication : Réponse : Non, le serveur est juste présent pour gérer les joueurs, il intégrer dans le code du jeu.

275 Itérer dans les tables Les tables (map) n’ont pas d’itérateurs.
Trois méthodes permettent de voir les tables comme des ensembles : keySet() retourne l’ensemble (Set) des clés ; values() retourne la collection des valeurs associées aux clés ; entrySet() retourne l’ensemble des couples (clé, valeur). Map m=…; Set clés = m.keySet(); Set couples = m.entrySet(); Collection valeurs = m.values(); On peut ensuite itérer sur ces ensembles : for(Iterator i=clés.iterator();i.hasNext();){ System.out.println(i.next());} for(Iterator i=couples.iterator();i.hasNext();){ for(Iterator i=valeurs.iterator();i.hasNext();){ Map.Entry e = (Map.Entry) i.next(); System.out.println(e.getKey() + « -> » + e.getValue()); }

276 Exemple de construction d’un index
On part d’une suite d’entrées formées d’un mot et d’un numéro de pages : 22, «Java» 23, «Iterateur» 25, «Java» 25, «Map» 29, «Java» Nous souhaitons obtenir l’index suivant : Iterateur [23] Java [22, 25, 29] Map [29] Chaque mot apparaît une fois, dans l’ordre alphabétique, et la liste des numéros de pages, où le mot est indexé, est donnée dans l’ordre croissant et sans répétition

277 /** Etape_1 */ class TestIndex{ // indépendante de l’implémentation public static void main(String[] args){ /** Constitution de l’indexation */ Index index = makeIndex(); /** Impression de l’indexation constituée */ index.print(); }

278 /** Etape_2 */ class TestIndex{ // indépendante de l’implémentation public static Index makeIndex(){ Index l_index = new Index(); l_index.put(22, «Java»); l_index.put(23, «Iterateur»); l_index.put(25, «Java»); l_index.put(25, «Map»); l_index.put(29, «Java»); return l_index; } public static void main(String[] args){ /** Constitution de l ’indexation */ Index index = makeIndex(); /** Impression de l ’indexation constituée */ index.print();

279 /** Etape_3 */ import java.util.*; class Index extends TreeMap{ // implementation dependant public void put(int page, String mot){ ... } public void print(){ Set clef = this.keySet(); for(Iterator i = clef.iterator(); i.hasNext(); ){ String c = (String) i.next(); System.out.println(c + «  » + this.get(c));}

280 /** Etape_4 */ import java.util.*; class Index extends TreeMap{ // implementation dependant public void put(int page, String mot){ Set numeros = (Set) this.get(mot); if (numeros == null) { // le mot n’est pas déjà référencé dans l’index numeros = new TreeSet()‏ this.put(mot,numeros); // c’est l’appel à la vraie méthode put } numeros.add(new Integer(page)); public void print(){ Set clef = this.keySet(); for(Iterator i = clef.iterator(); i.hasNext(); ){ String c = (String) i.next(); System.out.println(c + «  » + this.get(c));}

281 /** SOLUTION AGGREGEE */
import java.util.*; class Index extends TreeMap{ // implementation dependant public void put(int page, String mot){ Set numeros = (Set) this.get(mot); if (numeros == null) { // le mot n’est pas déjà référencé dans l’index numeros = new TreeSet()‏ this.put(mot,numeros); // c’est l’appel à la vraie méthode put } numeros.add(new Integer(page)); public void print(){ Set clef = this.keySet(); for(Iterator i = clef.iterator(); i.hasNext(); ){ String c = (String) i.next(); System.out.println(c + «  » + this.get(c));}

282 /** SOLUTION AGGREGEE */
class TestIndex{ // indépendante de l’implémentation public static Index makeIndex(){ Index l_index = new Index(); l_index.put(22, «Java»); l_index.put(23, «Iterateur»); l_index.put(25, «Java»); l_index.put(25, «Map»); l_index.put(29, «Java»); return l_index; } public static void main(String[] args){ /** Constitution de l’indexation */ Index index = makeIndex(); /** Impression de l’indexation constituée */ index.print();

283 Algorithmes de Collections
Les classes Collections et Arrays fournissent des algorithmes dont la performance et le comportement sont garantis. Toutes les méthodes de ces classes sont statiques (ce sont donc des méthodes de classe). Collections : min, max, dans une collection d’éléments comparables; sort pour trier des listes (tri-fusion); List a; … Collections.sort(a); binarySearch recherche dichotomique dans les listes ordonnées ; copy copie de listes : List source = …; List dest; Collections.copy(dest,source); synchronizedCollection pour « synchroniser » une collection : elle ne peut pas être modifiée durant l’exécution d’une méthode. NOTE : Pour la méthode copy(), la source n’est pas le premier argument mais le second.

284 Algorithmes de Arrays On obtient : $java Loto [13, 18, 27, 28, 35, 39]
binarySearch recherche dichotomique dans les tableaux ; equals teste l’égalité des contenus de 2 tableaux : int[] a, b …; boolean b=Arrays.equals(a,b); sort() trie un tableau (quicksort) : int a[]; … Arrays.sort(a); Exemple : Le Tirage du Loto import java.util.*; class Loto { public static void main(String[] args){ List boules = new ArrayList(49); for(int i=0; i<49; i++)‏ boules.add(new Integer(i+1)); Collections.shuffle(boules); // mélange List tirage = boules.subList(0,5); // les 6 premières Collections.sort(tirage); // tri System.out.println(tirage); //affichage du tirage }} On obtient : $java Loto [13, 18, 27, 28, 35, 39] $java Loto [2, 8, 12, 27, 33, 49] $java Loto [2, 3, 5, 28, 30, 31]

285 Retour sur les algorithmes de Arrays
Pour faire du traitement important et rigoureux il faut faire appel à des méthodes comme HipSort, shellSort . Dans l’exemple du tirage du loto précèdent, on a eu besoin de créer un ensemble de 49 boules. On a également eu besoin de les bouger avec la méthode shuffle() par exemple. Il a fallu ensuite piocher 6 (les 6 premières). (Collection.sort trie en ordre croissant) pour enfin afficher la liste des numéros. NOTE : random() est moins bien que la méthode shuffle() qui est plus complexe et qui permet d’avoir un résultat plus intelligent que celui en utilisant random().

286 Introspection C’est un design pattern qui permet de modifier dynamiquement une classe. Grâce à ces classes dynamiques, on peut ajouter des fonctions qui sont immédiatement disponibles à toutes les instances de cette classe. C’est la partie la plus délicate. 3h de travail personnel sont à prévoir pour un résultat incertain. La classe java.lang.Class permet de manipuler les classes et interfaces comme des objets; offre des possibilités d’introspection (c.-à-d. exploration des méthodes et constructeurs d’une classe). On peut ensuite récupérer un objet « méthode ». Les classes de ces objets sont définies dans java.lang.reflect : String s = « toto »; Class c = s.getClass(); interface I {}; Class c1 = I.class; Class c2 = Class.forName(« I »); Class c3 = Float.class; Une instance de la classe Class est associée à toutes les classes, interface, tableaux ou types primitifs. On peut appliquer les méthodes suivantes à un objet c de la classe Class : getDeclaredMethods() retourne un tableau d’objets de la classe java.lang.reflect.Method, les méthodes déclarées dans c; getMethods() retourne aussi les méthodes héritées ; getMethod(String, Class[] parameterTypes) recherche une méthode en fonction de son profil. Une méthode de la classe Method peut ensuite être invoquée par invoke().

287 Promo 2008-2009 R1 : Pierre Lebrun R2 : David N’Guyen
Avancer la lecture OBLIGATOIRE jusqu’au slide 209 La partie Introspection n’est pas à étudier On laisse les classes dynamiques arriver pleinement sur le marché ;-> (cf AS3)‏

288 On obtient : $java Test Mon Dec 8 12:33:11 CEST 2003
import java.lang.reflect.*; import java.util.Date; public class Test{ public static void main(String[] args) throws Exception{ Class classDate = Class.forName(«java.util.Date»); // ou «Date» // création d’une instance de la classe Date Object maDate = classDate.newInstance(); // récupération de la méthode toString() de la classe Date Method maSortie = classeDate.getMethod(«toString», null); // appel de la méthode toString() sur maDate System.out.println((String) maSortie.invoke(maDate, null))‏ Date aujourdhui = new Date(); System.out.println(aujourdhui); System.out.println(maDate); } On obtient : $java Test Mon Dec 8 12:33:11 CEST 2003 Mon Dec 8 12:33:11 CEST 2003

289 Le chargement des classes
Un chargeur de classe (classloader) est une instance d’une sous-classe de la classe abstraite java.lang.ClassLoader. Il charge le bytecode d’une classe à partir d’un fichier .class et la rend accessible aux autres classes. Principe du fonctionnement de la méthode loadClass() de la classe ClassLoader : 1- appel à findLoadedClass() pour voir si la classe n’est pas déjà chargée ; 2- demande de chargement de la classe à un chargeur parent obtenu par getParent() ; 3- en cas d’échec, appel de la méthode findClass()‏ 4- levée de l’exception ClassNotFoundException en cas de nouvel échec. public Class loadClass(String name) throws ClassNotFoundException { try { Class c = findLoadedClass(name); if (c != null) return c; ClassLoader parent = getParent(); try { c = parent.loadClass(name); if (c != null) return c; } catch (ClassNotFoundException e) {} c = findClass(name); if (c != null) return c; } catch (Exception e) {thow new ClassNotFoundException(name)} }

290 La méthode findClass() appelle une méthode defineClass() qui est la méthode de base de tout chargeur de classes. Elle : crée une instance de la classe Class et stocke la classe dans le chargeur. La signature de defineClass() : Class defineClass(String name, byte[] b, int off, int len) throws ClassFormatError import java.io.*; import java.lang.ClassLoader; public class VerboseClassLoader extends ClassLoader { public VerboseClassLoader(){ super(getSystemClassLoader()); /* chargeur parent en paramètre */ } public Class loadClass(String name) throws ClassNotFoundException { System.out.println(« Chargement de » + name ); try{ byte[] b = loadClassData(new File(name + «.class»)); return defineClass(name, b, 0, b.length) } catch (Exception e) { return getParent().loadClass(name)} } private byte[] loadClassData(File f) throws IOException{ FileInputStream entree = new FileInputStream(f); int length = (int) f.length(); int offset = 0; int nb; byte[] tableau = new byte[length]; while (length != 0) { nb = entree.read(tableau, offset, length); length -= nb; offset += nb; } return tableau; } ...

291 On obtient : $java VerboseClassLoader Chargement de A Chargement de B
public static void main(String[] args) thows Exception{ VerboseClassLoader cl = new VerboseClassLoader(); Class clazz = cl.loadClass(«A»); Object o = clazz.newInstance(); System.out.println(« Dans VerboseClassLoader : »); if (o instanceof A) System.out.println(«o instance de A»); else System.out.println(« o n’est pas instance de A »); System.out.println((o.getClass()).getClassLoader()); A o2 = new A(); System.out.println((o2.getClass()).getClassLoader()); } Pour faire tourner cette exemple, on se donne 3 classes vides B, C et D, et la classe A suivante : public class A extends B{ C c; D d; public A(){ System.out.println(« nouveau A() »); d = new D(); } public void inutile(){ c = new C(); } } L’appel à newInstance() crée un objet et charge les classes nécessaires à sa création. o et o2 n’appartiennent pas à la même classe : 2 classes de même nom (ici A) peuvent coexister dans la machine virtuelle si elles n’ont pas le même chargeur de classe. Ceci est extrêmement important pour la programmation réseau (cf. java.net). On obtient : $java VerboseClassLoader Chargement de A Chargement de B Chargement de java.lang.Object Chargement de java.lang.System Chargement de java.io.PrintStream nouveau A()‏ Chargement de D Dans VerboseClassLoader : o n’est pas instance de A

292 Partie V La programmation concurrente

293 La programmation concurrente
2- Processus légers 3- Les threads et la classe java.lang.Thread 4- Exclusion mutuelle 5- Synchronisation

294 5.1 Programmation concurrente
Définition : La programmation concurrente, c’est l’ensemble des mécanismes permettant l’exécution concurrente d’actions spécifiées de façon séquentielle. En java, 2 mécanismes permettent un ordonnancement automatique des traitements : la concurrence entre commandes du système (processus)‏ la concurrence entre processus légers de la machine virtuelle. NOTE : La programmation concurrente n’existe pas en Flash, c’est une phase cachée.

295 5.2 Processus légers Un processus léger ou thread correspond à un fil d’exécution. C’est un point de vue utilisateur. On distingue d’une part le lancement, d’autre part l’exécution. Il permet de faire les actions de façon concurrente, notamment pour les jeux en réseaux ou il est nécessaire d’en avoir pour restituer les informations de part et d’autre. S’il y a plusieurs processus légers, ils sont associés à un même programme, et ils s’exécutent dans le même espace mémoire. Lorsque l’on parle de processus légers en java, il y a 3 notions bien distinctes : un objet représentant le code à exécuter (la cible), et dont la classe de cet objet implémente l’interface Runnable ; un objet qui contrôle le processus léger, et dont la classe dérive de Thread ; un fil d’exécution, c.-à-d. la séquence d’instructions en cours d’exécution. C’est le code de la méthode run() de la cible. Mise en garde : Il ne faut surtout pas confondre Thread (Le contrôleur) et Runnable (le contrôlé). Pour illustrer cela il faut garder à l’esprit que Thread implémente Runnable et peut, par ce fait, s’auto-contrôler.

296 5.3 La classe java.lang.thread
Un objet de la class Thread ne représente pas un processus léger mais un objet de contrôle du processus léger. Au lancement d’un programme, la machine virtuelle possède un unique processus léger qui exécute le main() de la classe appelée. public class MaThread{ public static void main(String[] args) throws Exception{ Thread threadInitiale = Thread.currentThread(); threadInitiale.setName(« Thread initiale »); System.out.println(threadInitiale); Thread.sleep(1000); System.out.println(threadInitiale.isAlive()); Thread maThread = new Thread(); maThread.setName(« Ma thread »); System.out.println(maThread); System.out.println(maThread.isalive()); } On obtient : $java MaThread Thread[Tread initiale,5,main] true Thread[Ma thread,5,main] false Chaque processus léger : appartient à un groupe de processus légers : ici main ; et a une priorité : ici 5.

297 Retour sur le thread Le thread est un processus crée et géré à partir de Java. On gère manuellement la synchronisation des données. Dans le cadre réseaux, les clients ne partagent pas les mêmes espaces mémoire, il faut donc pouvoir gérer ces espaces mémoires. Avec les threads on a accès à un même espace mémoire d’où la synchronisation et la centralisation des informations. Un processus léger présente donc un objet représentant le code à exécuter (la cible). Comment créer un thread (voir l’exemple précèdent)? On peut le créer avec un constructeur ou alors récupérer le thread courant avec currentThread() ; On peut associer au thread initial un nom (setName() ;) On peut le faire dormir (sleep(tps en ms) ;) On peut vérifier si il est présent ou vivant (thread.isAlive() ;) renvoi true or false Tant que le thread n’est pas instancié, la fonction isAlive() aura pour valeur false…

298 Démarrage et terminaison
Démarrage d’un processus léger par la méthode start() du thread exécution du processus léger par le thread qui appelle la méthode run() de la cible qui implémente l’interface runnable La méthode run() se spécifie de 2 manières explicites : en implémentant la méthode run() de l’interface Runnable ; en redéfinissant la méthode run() de la classe Thread. Le processus se termine à la fin du run(). La classe Thread possède 7 constructeurs qui spécifient : le nom du processus léger, par défaut thread-i, le groupe du processus léger, un objet de la classe ThreadGroup, la cible (target) du processus léger : un objet implémentant l’interface Runnable qui précise la méthode run() à exécuter lors du démarrage du processus léger.

299 Le lapin et la tortue (Version 1)‏
On a besoin de deux processus indépendant, le lapin ira plus vite que la tortue. Pour le lapin on va surcharger le run() la classe lapin implémentant Runnable. Dans le run() il faut faire en sorte d’avoir 5 étapes pour voir l’avancée du lapin. Pour ces 5 étapes on va prendre la valeur de X qui va donner la valeur du temps. On regarde dans ce programme combien de temps le lapin met du temps t initial au temps x‐t (x‐t étant le temps qu’il a mis du point initial à t jusqu’à x). Ensuite on fait dormir le thread pendant 300 millisecondes et on va itérer cette manipulation 5X, et ainsi on peut voir combien de temps il a mis pour arriver. Classe des lapins: public class Lapin implements Runnable { public void run(){ long t = System.currentTimeMillis(), x = t; for(int i=0; i<5; i++) { x = System.currentTimeMillis(); System.out.println(« Lapin» + i + « au temps » + (x-t) + « ms.»); try { Thread.sleep(300); // un peu de repos } catch (InterruptedException e) {} } x = System.currentTimeMillis(); System.out.println(« Le lapin est arrivé au temps » + (x-t) + « ms.»); }

300 Pour les tortues c’est pareil:
public class Tortue implements Runnable { public void run(){ long t = System.currentTimeMillis(),x = t; for(int i=0; i<5; i++) { x = System.currentTimeMillis(); System.out.println(« Tortue» + i + « au temps » + (x-t) + « ms.»); try { Thread.sleep(500); // beaucoup plus de repos } catch (InterruptedException e) {} } x = System.currentTimeMillis(); System.out.println(« La tortue est arrivé au temps » + (x-t) + « ms.»); } La mise en place ensuite est la synchronisation des deux threads (du lapin et de la tortue): public class MesThreadVersion1{ public static void main(String[] args){ Runnable tortue = new Tortue(), lapin = new Lapin(); Thread tortueThread = new Thread(tortue), lapinThread = new Thread(lapin); tortueThread.start(); lapinThread.start();

301 l’accès au traitement et de la durée du traitement).
On obtient : Tortue 0 au temps 0 ms. Lapin 0 au temps 0 ms. Lapin 1 au temps 301 ms. Tortue 1 au temps 508 ms. Lapin 2 au temps 609 ms. Lapin 3 au temps 919 ms. Tortue 2 au temps 1017 ms. Lapin 4 au temps 1224 ms. Tortue 3 au temps 1535 ms. Lapin est arrive au temps 1542 ms. Tortue 4 au temps 2092 ms. Tortue est arrivee au temps 2557 ms. Les 2 thread ont la même priorité, donc même accès au processeur (équité au niveau de l’accès au traitement et de la durée du traitement). (L’équité d’accès n’est pas assurée sur toutes les implémentations des machines virtuelles) 1 2 3 4 Fin thread lente Fin thread rapide Le résultat nous montre l’avancé du temps de chacun des deux, on constate que le traitement machine rajoute du temps (ex pour la tortue que l’on attendait à 500ms se retrouve à 508ms) il y a donc un décalage.

302 Le lapin et la tortue (Version 2)‏
En Version 2 on peut mêler le thread et le run() associé . Ainsi on définit une classe Lapin qui étend le Thread et dans laquelle on surcharge le run().Idem pour la tortue. Classe des lapins étend Thread public class Lapin extends Thread { public void run(){ // inchangé } Classe des tortues étend Thread public class Tortue extends Thread { Mise en place public class MesThreadVersion2{ public static void main(String[] args){ Thread tortueThread = new Tortue(), lapinThread = new Lapin(); tortueThread.start(); lapinThread.start();

303 Terminaison d ’un processus léger
La terminaison normale d’un processus léger est la fin de la méthode run(). On peut forcer la terminaison d’un processus léger avant la fin du run() en terminant l’application. L’application se termine lorsque : RunTime.exit() est appelé par l’un des processus légers ; tous les processus légers qui n’ont pas été marqués daemon sont terminés. Un processus léger peut-être user ou daemon. On peut créer des processus légers daemon à l’aide de la méthode setDaemon() de la classe Thread. Exemple maThread.setDaemon(true); Priorités d’accès au processeur Les niveaux de priorité d’accès au processeur varient de 1 à 10. Des constantes de la classe Thread les définissent : Thread.MAX_PRIORITY 10 Thread.NORM_PRIORITY 5 Thread.MIN_PRIORITY 1 On peut définir et consulter un niveau de priorité en appliquant l’une des méthodes de l’objet de contrôle du processus léger : setPriority()‏ getPriority()‏ setMaxPriority()‏

304 Exclusion mutuelle Une opération atomique est une opération qui ne peut-être interrompue une fois qu’elle a commencé. Java garantit l’atomicité de l’accès et de l’affectation des variables de type primitif (hormis long et double). Java possède un mécanisme d’exclusion mutuelle entre processus légers. Il garantit l’atomicité d’exécution de morceaux de code. Un verrou peut-être associé à une portion de code et permet d’exclure l’accès de 2 processus légers sur cette portion. Pour cela on synchronise une portion de code relativement à un objet en utilisant le mot clef synchronized : synchronized, comme modificateur d’une méthode, s’applique au code d’une méthode relativement à l’objet courant. synchronized(obj){… portion de code …}; Durant l’exécution d’un processus léger A d’une portion de code synchronized, tout autre processus léger essayant d’exécuter une portion de code synchronized relative au même objet est suspendu. Une fois A terminé, un seul des processus légers en attente est relancé.

305 Exemple : tableau (variante)‏
public class Tableau { private int[] t; public synchronized int somme(){ int s=0; for(int i=0;i<tableau.length;i++) s+=t[i]; return s; } public synchronized void setElement(int i, int j){ t[i]=j; }; Pendant l’exécution d’un x.setElement() ou d’un x.somme() dans un processus P, tout autre processus Q qui essaie de faire x.setElement() ou x.somme() sur le même x est suspendu. Exemple : tableau (variante)‏ public class Tableau { private int[] t; public synchronized int somme(){ int s=0; for(int i=0;i<t.length;i++) s+=t[i]; return s; } public synchronized void setElement(int i, int j){ if ((i <0) || i>= t.length) throw new IndexOutOfBoundsException(); synchronized(this){t[i]=j;}; Dans cette version, seule l’affectation est verrouillée.

306 Sûreté et vivacité Quelques notions :
sûreté (safety) : rien de faux ne peut se produire. L’exclusion mutuelle règle/gère le problème de l’accès concurrent en écriture : R/R pas de problème W/W problème mais R/W ou W/R problème d’accès à résoudre vivacité (liveness) : tout processus peut s’exécuter. La non vivacité d’une application ou d’un processus est effective lorsqu’il y a : famine (contention) : un processus léger est empêché de s’exécuter parce que un, ou plusieurs, processus plus prioritaire(s) accapare(nt) le processus ; endormissement (dormancy) : un processus léger est suspendu mais jamais réveillé ; terminaison prématurée ; interblocage (deadlock) : plusieurs processus légers s’attendent mutuellement avant de continuer.

307 Synchronisation entre processus légers
Java propose 2 mécanismes : attente / notification avec wait() et notify() : wait() appelé sur un objet suspend le processus courant qui attend une notification d’un autre processus via le moniteur de l’objet, notify() appelé sur un objet libère un processus léger en attente par wait() sur le moniteur du même objet ; attente de terminaison avec join() : join() est appelé sur l’objet de contrôle d’un processus léger dont la terminaison est attendue. Le processus courant est alors interrompu jusqu’à la terminaison du processus léger attendu. Les méthodes wait(), join() et sleep() peuvent être interrompues (et les processus effectuant leur appel peuvent alors être débloqués). La méthode bloquante lève une exception InterruptedException qui peut être captée / interceptée.

308 Résumé : Exclusion mutuelle, Sûreté et vivacité, Synchronisation entre processus légers
L’idée derrière est qu’il y a des opérations qui peuvent s’interrompre à n’importe quel moment. Il faut identifier dans un programme ou l’on va empêcher tout autre traitement d’intervenir afin de ne pas bruler une étape dans l’application qui risquerait de causer des problèmes pour la suite des traitements, c’est ce que appel l’exclusion mutuelle. Le principe est de garder donc « l’atomicité » d’une opération qui ne peut être interrompu une fois qu’elle a commencé. NOTE : Lorsqu’on met en place un jeu multi‐joueurs il faut synchroniser les éléments du tableau d’attente de connexion à la partie afin de pouvoir dire si le tableau est plein, que toutes les places sont prises… Sureté et vivacité La synchronisation est très importante pour des applications proposant une interaction multiple. Veillez à régler les problèmes de lectures/écritures ou écriture/lecture afin de ne pas produire d’erreurs lors de l’accès concurrent à des données. Synchronisation entre processus légers Java propose deux mécanismes de synchronisation entre processus léger : -Attente/notification avec wait() et notify() -Attente de terminaison avec join() NOTE : La méthode join() appelée dans la méthode run() d'un processus léger, via le contrôleur d'autres threads permet de bloquer ce processus léger jusqu'à la mort des autres threads (threads joints). Wait() permet de suspendre le processus courant et notify() permet de libérer un processus léger en attente par wait() sur le moniteur du même objet.

309 Promo 2008-2009 Fin CM 10 GRASSWILL Julien R1 WOERLY Maxime R2
Ce cours fut le dernier de l’année L’évaluation du jeu Java portera sur toute la partie du cours vue jusqu’à cette partie. Et concernant le projet, il sera évalué en conséquence et tout ce qui suit cette partie du cours sera du bonus. L’implémentation correcte du projet, si elle intègre de l’interface, du réseau, du jdbc ou du XML augmentera la grille d’évaluation du projet au‐delà de 20. NOTE : La compréhension des usages qui sont faits dans ce cours permet de réaliser des programmes complexes en peu de lignes de code. Si des problèmes sont rencontrés d’ici à cinq ans, ne pas hésiter à contacter M. Canalda.

310 TP 10 Groupe A Jeudi 11 décembre 2008 1er Rapporteur : Oleg ERIZANU 2eme Rapporteur : Sonia GOUDEAU
Déroulement de la séance : Appel et nomination des rapporteurs avancement des projets (en tableaux) ; tour de table Remarque: La grande majorité des groupes ont dépassé 50% d’avancement global, sauf l’équipe « Amertume » avec le projet « Conte macabre » (~28%).

311 Nom du groupe: « Plast’ink » avec le projet « Renaissance »
Pourcentage global : ~54% Problèmes rencontrées : aucun

312 Nom du groupe: « Sphere Light » avec le projet « Vivre sans être(s) »
Pourcentage global : ~65% Problèmes rencontrées : lancer deux écouteurs de réseau à la fois (en parallèle).

313 Nom du groupe: « Ideo » avec le projet « Le monde de Clara »
Pourcentage global : ~56% Problèmes rencontrées : l’algorithme de Dischtrat (calculer le chemin le plus court entre deux points).

314 Nom du groupe: « Amertume » avec le projet « Conte macabre »
Pourcentage global : ~28% Problèmes rencontrées : l’interface

315 Nom du groupe: « Forgotten fridge » avec le projet « Buster et Charlie » (groupe 1)
Pourcentage global : ~64% Problèmes rencontrées : - traduire l’algorithme en code Java - l’intégration du graphisme

316 Conclusion TP10 groupe A:
1. Seul un groupe n’a pas encore terminé sa version texte mono-joueur monoposte sans thread. 2. 4 groupes sur 5 ont l’intention d’intégrer l’interface graphique au jeu. 3. Seuls 2 groupes sur 5 ont abordé l’aspect réseau. 4. Du travail personnel a été réalisé dans chacun des groupes.

317 TP 10 Groupe B et C Jeudi 11 décembre er Rapporteur : Mikaël Geljić 2eme Rapporteur : Rémi Campistron Déroulement de la séance : L’objectif du TP, comme maintenant depuis quelques séances, est de jauger l’avancement général des différents groupes de projet, et de répondre en particulier à des questionnements soulevés en phase de réalisation des applications. L’outil qui fait maintenant presque référence pour évaluer l’avancement des groupes, est un tableau à double entrée : génériquement, chaque ligne est une contrainte du projet, les colonnes représentent quant à elles les différents groupes. Nous avons toutefois proposé une variante au tableau utilisé par le groupe A en séance du 11 Décembre de 11h à 13h. D’une part le groupement des lignes concernant le diagramme de classes, et de celles concernant la version en cours, d’autre part l’utilisation de 2 colonnes pour chaque groupe : « fait » et « à faire », qui permet éventuellement de donner plus de granularité dans la description des tâches. L’idée est de bannir les pourcentages, déjà critiqués en séance de TP9, qui manquent de représentativité et peuvent être arbitraires.

318 Précisions sur le diagramme de classes
Outre les contraintes de faire apparaître les interfaces et les exceptions sur le diagramme, voire éventuellement les classes de tests unitaires et tests d’intégration, des incertitudes persistaient quant à y dresser une liste exhaustive de toutes les méthodes utilisées, car dans certains cas il se peut qu’elles soient particulièrement nombreuses. La réponse apportée par M.Canalda est qu’il est effectivement important de faire figurer toutes les méthodes, par leur signature comprenant leur portée (public, private, protected…), leur type retourné et leurs paramètres admis. Il convient également de préciser dans les cas de polymorphisme s’il s’agit de la déclaration d’une méthode (généralement dans les interfaces) ou de sa définition, voire redéfinition (éventuellement sur des classes héritées).

319 Avancement des groupes de projet

320

321 Intervention sur les interfaces
La programmation orientée interfaces étant obligatoire, on ne doit pas trouver dans une classe un attribut dont le type est directement une autre classe du projet. A l’inverse, pour chaque type d’objet, on doit trouver un doublon classe, comprenant les définitions, et interface, abstraite, comprenant exclusivement les déclarations des attributs et méthodes publiques ou statiques. Ainsi, on déclare puis instancie un objet niveau – pour reprendre un exemple du groupe A - de cette façon : INiveau mon_niveau = new Niveau(); Le type de mon_niveau est abstrait mais l’instance référencée à l’adresse de mon_niveau est un nouveau Niveau. Bien entendu, la classe Niveau implémente l’interface INiveau !

322 L’idée globale est de décorréler l’usage de l’implémentation, plusieurs intérêts à cela :
♠ Le code d’une fonctionnalité particulière se modifie au sein d’une méthode, et ne nécessite pas de réécriture de codes dispersés dans l’application. ♠ L’interface reste intacte, et les modifications apportées au niveau implémentation n’ont pas d’impact sur le reste du fonctionnement de l’application. ♠ Tendre naturellement vers du polymorphisme : un type abstrait peu ainsi recevoir plusieurs implémentations différentes.

323 TP 10 Groupe C Jeudi 11 décembre er Rapporteur : Pierre Damien Truer 2eme Rapporteur : Pierre Emmanuel Remy Déroulement de la séance : Tour de table Groupe 1 i-travel Groupe 2 warning Groupe 3 Buster & Charlie Synthèse Visualisation du code du groupe « Warning » Le fonctionnement du jeu Les problèmes rencontrés Aparté sur le choix des options Intégration Multimédia Arts Numériques Son

324 Utilisation de frame ou applet
Groupe 1 : Doubi’Studio, film i-travel : Anaïs A, Aki A, Pierre Damien T, Guillaume V, Olivier V Diagramme de Classes Le Diagramme de classe est complétement finalisé. Je vous rappelle les classes qui s'y trouve : Pièces Pièces malus (inversion des touches et rotations du puzzle) Pièces bonus (efface le malus) Classe volume : limite le nombre de vie Classe ipod : associe à la pièce a afficher Classe déplacement Classe validation des pièces Classe tableau L'avancée du jeu Version Texte : Le jeu est fini dans sa version texte. Il fonctionne parfaitement. Il reste cependant à intéger une exception. Le groupe ne s 'est encore pas mis entièrement d'accord sur les caractéristiques de celle-ci. Version Graphique : L'interface graphique est réalisée. Ella a été validée par les autres membres du groupes. Cette interface a été découpée en vue de l'intégration dans le jeu. Le jeu d'i-travel n'est pas encore disponible en version graphique. Il faudra se contenter pour l'instant de la version texte. Mais l'objectif de ce TP pour ce grouge est de commencer à réfléchir et à intégrer le graphisme afin d'avoir un jeu poussé au maximum. Utilisation de frame ou applet Olivier Viatour a commencé à travailler sur les applets à l'aide de tutoriels trouvés sur Internet et les exercices vus en cours. Mais ces essais se sont avérées peu concluant. En effet, Oilivier n'a pas réussi à afficher correctement l'applet. Les autres membres du groupes n'ont pas encore essayer d'intégrer le jeu avec des frames ou des aplets. Travail Personnel Rien de plus que ce qui a été evoqué lors du TP 7 et 8. Les exercices du cours ainsi que des petits tutoriels sur le Web ont été refait. Multijoueurs / Réseau Ces notions n'ont pas été encore abordés et n'y seront sans doute pas faute de temps.

325 Utilisation de frame ou applet
Groupe 2 : Studio Clochette, film Warning : Philippe M, Sisalio P, Pierre Emmanuel R Diagramme de Classes Le diagramme de classe est finalisé à hauteur de 90%. Il reste à le modifier en rajoutant des méthodes et des attributs. Les classes privates doivent être déclarées dans le diagramme de classe à la fin de la programation. L'avancée du jeu Version Texte : Le jeu est bien avancé dans sa version texte. Il fonctionne presque tout à fait. Il reste cependant à intéger une exception et à corriger un petit disfonctionnement du programme au niveau du défilement (nous y reviendrons dans la deuxième partie). Version Graphique : L'intégration graphique en est au même point que pour le groupe i-travel. L'interface est réalisée, il ne reste plus qu'à l'intégrer. Utilisation de frame ou applet Il n'y a pas eu d'utilisation de frame ou d'appet. L'objectif de ce tp pour le groupe Warning est donc de commencer à travailler sur ce sujet. Travail Personnel Rien de plus que ce qui a été evoqué lors des précédents tps. Multijoueurs / Réseau Ces notions n'ont pas été encore abordés et n'y seront sans doute pas faute de temps.

326 Utilisation de frame ou applet
Groupe 3 : Buster & Charlie 2 : Céline C, Jules, Tarek Diagramme de Classes Le diagramme de classe est fini. Il ne devrait pas y avoir de modification à apporter. L'avancée du jeu Version Texte : Le jeu est bien avancé dans sa version texte. Il fonctionne presque tout à fait. Il reste cependant à programmer le « timer » et une exception. Celle-ci n'a pas non plus été défini pour le moment. Version Graphique : L'intégration graphique en est au même point que pour les deux groupes précédents. Utilisation de frame ou applet Il n'y a pas eu d'utilisation de frame ou d'appet. Travail Personnel Rien de plus que ce qui a été evoqué lors des précédents tps. Multijoueurs / Réseau Ces notions n'ont pas été encore abordés et n'y seront sans doute pas faute de temps.

327 Synthèse des 3 projets: Avec ce tableau on peut voir que ces trois groupes sont au même stade d'avancement.

328 Visualisation du code « Warning »
Les problèmes rencontrés Identifier son problème c'est montrer que l'on connaît son code. En connaissant ce qu'il ne vas pas, il est plus facile de pouvoir paliier au problème. Demandez à quelqu'un de vous aider. Savoir le problème c'est un premier pas vers l'établissement d'un diagnositc. Petit Aparté sur les options du second semestre Il ne faut pas se laisser abuser par les intitulés des options. « Art Numérique » ne veut pas dire « aucun enseignement de programmation » : c'est FAUX. Il faut avoir des compétences aussi en programmation pour faire ce parcours. Il est demandé des aptitudes en mathématiques et en géométrie. Il faut avoir des compétences en programmation, notamment C et C++. De même que ceux qui envisagerait la filiaire « Son », il faut avoir un goût prononcé pour tous ce qui est de l'intégration. Une démonstration aura lieu ce vendredi 12 décembre 2008 au Palot à montbéliard. Cette démonstration est faite par des étudiants de l'option Son. Le rendez-vous est fixé à 18h00. « Ce que vous avez été capable de faire en six semaines c'est extraordinaire !! Demander aux personnes qui ont fait un DUT informatique et ceux qui sont en écoles d'ingénieur ils vous le diront; » Philippe Canalda.

329 Exemple : les tourneurs et le compteur
Cinq processus légers, les tourneurs, veulent faire tourner un compteur (le compteur) qui compte modulo 5. La classe du compteur : public class Compteur { private int max; // 5 dans l’exemple private int count = 0; // initialisation importante public Compteur(int max){this.max=max;}; public int getMax(){return this.max;}; public int getValue(){return this.count;}; public synchronized void increment(){ this.count = (this.count +1) % this.max ; // l’objectif du tourneur } La règle du jeu : un Tourneur ne peut faire tourner le compteur que s’il est égal à son numéro identifiant.

330 On obtient : $java Tourneur Tourneur 0 est créé.
La classe du Tourneur : public class Tourneur extends Thread { private Compteur c; // le compteur private int numero; // l’identifiant du tourneur public Tourneur(int numero, Compteur c){ /* Construction récursive des tourneurs identifiés entre numero et max -1 */ System.out.println(«Tourneur »+numero+ «est créé.»); this.numero=numero; this.c=c; if ((numero + 1) < c.getMax())‏ new Tourneur(numero +1, c); System.out.println(« Tourneur » + numero + « démarre.»); this.start(); } public void run() {… //définition à venir}; public static void main(String[] args){ Compteur c = new Compteur(5); new Tourneur(0,c); On obtient : $java Tourneur Tourneur 0 est créé. Tourneur 1 est créé. Tourneur 2 est créé. Tourneur 3 est créé. Tourneur 4 est créé. Tourneur 4 démarre. ...

331 Tourneur 0 hors de l’etape 0 Tourneur 1 hors de l’etape 0
public void run() { try{ for(int etape=0; ;etape++){ System.out.println(«Tourneur » + this.numero + « dans l’etape »+etape); synchronized(this.c){ while (this.numero != this.c.getValue())‏ this.wait(); // this.c.getValue() == numero du thread Tourneur courant System.out.println(« Tourneur » + this.numero + « hors de l’etape »+etape); this.c.increment(); this.notifyAll(); // libère tous les autres thread suspendus }; // fin de la portion de code de synchronisation }; // fin du for } catch(InterruptedException e){} } Tourneur 4 démarre Tourneur 4 dans l’etape 0 Tourneur 3 démarre Tourneur 3 dans l’etape 0 Tourneur 2 démarre Tourneur 2 dans l’etape 0 Tourneur 1 démarre Tourneur 1 dans l’etape 0 Tourneur 0 démarre Tourneur 0 dans l’etape 0 Tourneur 0 hors de l’etape 0 Tourneur 1 hors de l’etape 0 Tourneur 2 hors de l’etape 0 Tourneur 3 hors de l’etape 0 Tourneur 4 hors de l’etape 0 Tourneur 4 dans l’etape 1 Tourneur 3 dans l’etape 1 Tourneur 2 dans l’etape 1 Tourneur 1 dans l’etape 1 Tourneur 0 dans l’etape 1 Tourneur 0 hors de l’etape 1 Tourneur 1 hors de l’etape 1 ...

332 Exemple : maître et esclave
Un esclave « travaille » : public class Esclave implements Runnable{ private int result; public int getResult(){return this.result;}; public int durTravail(){return 0;}; public void run(){this.result=durTravail();}; } Le maître fait travailler l’esclave, et attend par join(), la fin du processus esclave. public class Maitre implements Runnable{ public void run(){ Esclave e = new Esclave(); Thread esclave=new Thread(e); esclave.start(); // le maître fait quelque chose d’autre … // puis ensuite il attend la fin du travail de l’esclave try { esclave.join(); // attente de la fin du run()‏ } catch(InterruptedException e) {}; int result=e.getResult(); System.out.println(result);

333 Mise en place: public class TestMaitre { public static void main(String[] args){ Maitre m=new Maitre(); Thread maitre = new Thread(m); maitre.start(); }

334 On obtient : $java MaCible 0.83456875903 0.23545436768897
Variables locales à un processus léger On peut simuler des variables locales à chaque processus léger en : créant un objet de la classe ThreadLocal ; y accédant par Object get(); le modifiant par void set(Object o); Exemple : public class MaCible implements Runnable{ public ThreadLocal v =new ThreadLocal(); public void run(){ v.set(new Double(Math.random())); System.out.println(v.get()); } public static void main(String[] args){ MaCible c=new MaCible(); Thread t1=new Thread(c), t2=new Thread(c); t1.start(); t2.start(); On obtient : $java MaCible

335 SHARED MEMORY FOR JAVA THREADS
* What variables are shared - Rule: "All that's visible is shared" - However: - Variables created in a method are local (stack)‏ - Objects are shared (heap?), but in order to be used by other threads, they must be visible to them (e.g. having a visible object that points to them)‏ - NB: if each thread executes in run(): Toto t = new Toto(); then each thread creates a Toto object, and t points to its copy (different objects with the same name)‏ * Putting main thread to do the same work as the others ** Method 1: run() (without start()) called from the main thread MyThread master = new MyThread(); master.createThreads(); // create P-1 threads master.run(); // do itself the same work

336 ** Method 2: through a static method
public class MT extends Thread { int monid; MT (int id){ this.monid = id; } public void run (){ Work.travail (monid); public static void main (String[] args){ new MT(1).start(); new MT(2).start(); Work.travail(0); class Work public static void travail(int id){ // put here all the work to do by each thread System.out.println ("id = " + id);

337 Partie VI Programmation Graphique : Swing / Awt

338 La programmation graphique
Objectif : Comment écrire des programmes (modernes et pages web) avec une GUI (Graphic User Interface) : a- spécifier et positionner des composants b- Gérer des événements c- ajouter des éléments d’interface 1- Introduction à Swing 2- Les composants Awt : evenments, components, containers, drawing 3- La structure des Jframe, buttons, menus

339 Info 2006-2007 Prise de notes du dernier cours par Jérémy Laurent
Ce cours est le dernier. L’évaluation portera sur toute la partie du cours vue jusqu’à cette partie. Pour le projet tout ce qui suit est du bonus. L’implémentation correcte du projet, si elle intègre de l’interface, du réseau, du jdbc ou de l’xml, cela augmentera la grille d’évaluation du projet au-delà de 20.

340 Introduction à Swing Swing est le nom officiel du kit de développement d’interface graphique léger. Swing fait partie des classes JFC (Java Foundation Class). Les JFC ne se limitent pas à swing en offrant des API d’accessibilité, de dessin 2D et de fonctionnalités drag and drop. Swing ne remplace pas AWT mais fournit des composants d’interface plus performants. La gestion d’événements de Swing et de AWT sont identiques et issus de Java 1.1. Swing est moins dépendant de la plate-forme d’exécution, look and feel. Mais AWT est plus performant pour les composants lourds, c’est-à-dire les applications qui utilisent des ressources du système d’exploitation de la machine hôte. Il est possible d’améliorer un look and feel existant voir en concevoir un nouveau : cf. (rubrique Swing connection)‏

341 Partie VI a Les composants awt de Java

342 Les composants awt de Java
(Abstract Windowing Toolkit)‏ 1- Composants et conteneurs 2- Evénements 3- Dessins

343 Composants et conteneurs
Un composant est un objet de base de l’interface utilisateur de Java. C’est un objet d’une classe dérivant de la classe java.awt.Component comme : fenêtres, boutons, zones de dessin, menus, barres de défilement, … Un composant est généralement inséré dans un conteneur. Un conteneur est un objet de la classe java.awt.Container qui regroupe des composants. Un gestionnaire de placement (Layout Manager) gère la géométrie des composants ainsi que la disposition des composants dans un conteneur Component Container Window Frame Dialog FileDialog Panel Applet ScrollPane

344 Gestionnaire de placement
Les gestionnaires de placement sont des objets de classes qui implémentent l’interface LayoutManager. Comme exemples de classes implémentant l’interface LayoutManager nous avons: FlowLayout, GridLayout, BorderLayout, BoxLayout Chaque conteneur a un gestionnaire de placement par défaut : setLayout() de la classe Container pour le modifier : setLayout(new FlowLayout()); lorsque des objets sont ajoutés dans un conteneur, la mise à jour peut se demander par la méthode validate() de la classe Component.

345 Evénements Le modèle émetteur-auditeur
Les programmes à interfaces graphiques sont pilotés par des événements. Un thread spécial, nommé EventDispatchedThread, est créé par la machine virtuelle. Il est en charge de l’interception (lecture) des événements et de la distribution de ces événements. Un événement correspond à une action simple (enfoncement de la souris, pression d’une touche, ...). On le désigne parfois par le vocable d’événement élémentaire. Un événement sémantique consiste en une séquence d’événements élémentaires (clic de souris, ...) synthétisés en un événement unique. Le modèle émetteur-auditeur Un événement est émis (fired) par un composant. Un événement est transmis aux auditeurs enregistrés. Les auditeurs exécutent des méthodes en fonction de l’événement reçu. Plusieurs auditeurs peuvent être enregistrés pour un événement. Il existe différentes classes d’auditeurs (listeners) qui ont leurs propres méthodes. Ces classes sont des interfaces à implémenter. Exemple : créer des boutons en cliquant sur le premier (Exemple)‏

346 Créer des boutons en cliquant sur le premier
import java.awt.*; import java.awt.event.*; class BoutonNumerote extends Button { static int numero = 1; BoutonNumerote(){ setLabel(« Bouton »+this.numero); this.numero++; }; } public class BoutonFrame extends Frame { public BoutonFrame() { setTitle(« Création de boutons à la volée »); Button b = new BoutonNumerote(); add(b); b.addActionListener(new BoutonListener()); setSize(200,200); setVisible(true); public static void main(String[] )‏ new BoutonFrame(); } class BoutonListener implements ActionListener{ public void ActionPerformed(ActionEvent e)(){ add(new BoutonNumerote()); validate();}

347 Version appliquette import java.awt.*; import java.awt.event.*;
import java.applet.Applet; class BoutonNumerote extends Button { static int numero = 1; BoutonNumerote(){ setLabel(« Bouton »+numero); numero++; }; } public class BoutonApplet extends Applet { public void init() { BoutonNumerote b = new BoutonNumerote(); add(b); b.addActionListener(new BoutonListener()); class BoutonListener implements ActionListener{ public void ActionPerformed(ActionEvent e)(){ add(new BoutonNumerote()); validate();} Rmq : la classe BoutonListener est une classe interne (inner class) à BoutonApplet.

348 Info Cedric Sittre et Alexandre Viriot

349 Version appliquette + compacte
import java.awt.*; import java.awt.event.*; import java.applet.Applet; class BoutonNumerote extends Button { static int numero = 1; BoutonNumerote(){ setLabel(« Bouton »+numero); numero++; }; } public class BoutonApplet extends Applet implements ActionListener{ public void init() { BoutonNumerote b = new BoutonNumerote(); add(b); b.addActionListener(this); public void ActionPerformed(ActionEvent e)(){ add(new BoutonNumerote()); validate();} Exemple : compter les clics sur les boutons (exemple)‏