3. POO en Java
Transcription
3. POO en Java
3. POO en Java Olivier Curé UMLV [page 99 ] Déclaration d'une classe Il est préférable de définir une unique classe par fichier java. Cette classe est alors publique et donne son nom au fichier Exemple : public class Cercle { ... // définition des membres } Le nom du fichier est nécessairement Cercle.java (respecter la casse). Olivier Curé UMLV [page 100 ] Création d'un objet : new La seule manière de créer un objet en Java est d'utiliser l'opérateur new. Cet opérateur doit être suivi du nom de la classe à instancier. Exemple : String chaine = new String(); String salut = new String(" Bonjour "); ParserXML parserXml = new ParserXML(); Syntaxe : <classe> <référence sur objet> = new <constructeur de la classe>; Olivier Curé UMLV [page 101 ] Opérateur new L'instanciation d'une classe déclenche les actions suivantes : ● création de l'objet, ● allocation mémoire nécessaire à cet objet, ● appel du constructeur de la classe. Olivier Curé UMLV [page 102 ] Constructeur en Java Toute classe possède un constructeur par défaut, implicite. Un constructeur porte nécessairement le même nom que sa classe, sans type de retour. Il peut y avoir plusieurs constructeurs dans une même classe. Ceux-ci diffèrent par le nombre et la nature de leurs paramètres. Olivier Curé UMLV [page 103 ] Destructeur en Java En java, la destruction des objets est prise en charge par le garbage collecteur (GC) ou ramasse-miettes. Le GC détruit les objets pour lesquels il n'existe plus de référence. Aucune garantie n'est apportée quant à la destruction des objets. On peut forcer le mécanisme à l'aide de la méthode finalize. Olivier Curé UMLV [page 104 ] Critéres de visibilité des membres L'accessibilité des membres est pondérée par des critères de visibilité donnés par les modificateurs suivants : ● public : accessible hors de la classe ● private : accessible uniquement dans la classe ● protected: accessible dans toutes les classes du package et ses dérivées ● (pas spécifié) : accessible dans toutes les classes du package. Olivier Curé UMLV [page 105 ] Règles d'accès aux membres accessible à : public protected package private Classe de définition Oui Oui oui oui Classe du même package oui oui oui non Sous-classe dans un oui oui non non oui non non oui package différent Classe qui n'est pas une sous-classe dans un package différent Olivier Curé UMLV [page 106 ] Réflexivité d'un objet : this Tout objet se " voit " lui-même. Le mot clé this permet de montrer qu'une méthode accède à ses propres propriétés et/ou méthodes. Olivier Curé UMLV [page 107 ] Invocation de méthodes L'invocation d'une méthode s'effectue en nommant l'instance et en la faisant suivre du nom de la méthode avec la liste des paramètres, éventuellement vide. <objet>.methode(parametres); Le passage de paramètres dans les méthodes dépend de la nature des paramètres : - par référence pour les objets. - par copie pour les types primitifs. NB : - Pour être invoquées à l'extérieur de la classe, les méthodes doivent faire partie de l'interface publique de l'instance. Olivier Curé UMLV [page 108 ] Invocation des attributs Il est possible d'accéder aux attributs à condition que la définition de la classe le permette. <objet>.nom_attribut; La spécification de l'objet n'est pas obligatoire si l'accès est réalisé au sein d'une méthode de la classe courante. Le respect des principes de l'encapsulation impose de fournir des méthodes d'accès aux attributs. Olivier Curé UMLV [page 109 ] Exemple invocation des attributs public class Exemple { public int x; private int y; ...} public class ExempleTest { public static void main(String args[]) { Exemple ex1 = new Exemple(); ex1.x = 10; ex1.y =5; System.out.println(ex1.x + " " + ex1.y); } } Correct ? Olivier Curé UMLV [page 110 ] Exemple: classe Cercle 4 méthodes dont 2 constructeurs. ● 2 propriétés dont une constante. ● Le fichier se nomme Cercle.java ● public class Cercle { private double rayon; public static final double PI = 3.14159; public Cercle() { rayon = 1.0; } public Cercle(double rayon) { this.rayon = rayon; } public double circonference() { return 2*PI*rayon; } public double surface() { return PI*rayon*rayon; } } Olivier Curé UMLV [page 111 ] Exemple: classe CercleTest public class CercleTest { public static void main(String args[]) { Cercle c1 = new Cercle(); System.out.println(" Surface de c1 = " +c1.surface()); Cercle c2 = new Cercle(5.5); System.out.println(" Circonference de c2 = " + c2.circonference()); } } Le fichier CercleTest.java est exécutable (il y a une méthode main). Olivier Curé UMLV [page 112 ] Les tableaux en Java En java, les tableaux sont considérés comme des objets : - création à l'aide de l'opérateur new, - héritage des méthodes d'instances de Object. - les variables du type tableau manipulent des références aux tableaux, - possèdent une propriété d'instance final int length qui donne la taille du tableau. Olivier Curé UMLV [page 113 ] Les tableaux en Java (2) Déclaration et création int[] monTableau = new int[10]; Déclaration, création et initialisation int[] monTableau2 = {1,2,3,4,5}; Un tableau en Java s'exploite de la même manière qu'un tableau en C. monTableau[0] = 0; // initialisation de la 1ère cellule Il est possible de manipuler des tableaux multidimensionnés. int[][] monTableau3 = new int[][]; Olivier Curé UMLV [page 114 ] Membres statiques Rappel : membres = méthodes + attributs En java, on définir un membre de classe à l'aide du mot réservé static. Dans la classe Cercle, PI est statique => Quelque soit le nombre d'instances de Circle, il n'y aura qu'un exemplaire de PI. Pour accéder à un membre statique, il faut le précéder du nom de sa classe. Olivier Curé UMLV [page 115 ] Membres statiques 2 Explication de "System.out.println(..)" La classe System contient une propriété de classe dont le nom est out. L'objet System.out appelle une méthode objet de nom println(). Olivier Curé UMLV [page 116 ] Mot réservé : final Le mot réservé final déclare une constante et impose à l'attribut de ne pouvoir être modifié par la suite. Exemple : public static final double PI = 3.14159; Olivier Curé UMLV [page 117 ] 4. Héritage, classe abstraite, interface et paquetage Olivier Curé UMLV [page 118 ] Héritage En java, il n'existe que de l'héritage simple. L'héritage multiple est : trop complexe et peut provoquer des problèmes sur les références(C+ +). Le parent commun à toutes les classes est : Object. La définition d'une sous-classe est réalisée à l'aide du mot réservé extends. Cette sous-classe hérite alors des méthodes et attributs de sa super-classe. L'opérateur instanceOf permet de déterminer la classe d'une instance (résultat booléen). Olivier Curé UMLV [page 119 ] Constructeur d'une sousclasse Le constructeur d'une sous-classe invoque le constructeur de sa super-classe (première instruction). Le désignateur super permet de faire référence à sa super-classe. Olivier Curé UMLV [page 120 ] Exemple d'héritage public class Ellipse { Ellipse public double r1, r2; public Ellipse(double r1, double r2) {this.r1 = r1; this.r2 = r2;} public double surface() {...} } public class Cercle extends Ellipse { public Cercle(double r) {super(r,r);} public double rayon() {return r1;} } Ellipse e = new Ellipse(2.0, 3.0); Cercle c = new Cercle(4.0); System.out.println(e instanceof Cercle); // false System.out.println(e instanceof Ellipse); // true System.out.println(c instanceof Cercle); // true System.out.println(c instanceof Ellipse); // true:c dérive de Ellipse System.out.println(c instanceof Object); // true Cercle Olivier Curé UMLV [page 121 ] Redéfinition de méthodes Une méthode héritée peut être redéfinie dans une sous-classe : il faut alors la réécrire en conservant la même signature (paramètres et type de retour). Exemple : Cercle peut redéfinir " surface " de Ellipse. La méthode redéfinie peut exploiter super sur la méthode de sa super-classe. Olivier Curé UMLV [page 122 ] Exemple de redéfinition de méthodes public class Cercle extends Ellipse { public Cercle(double r) {super(r,r);} public double rayon() {return r1;} public double surface() {... super.surface(); ... } } Olivier Curé UMLV [page 123 ] Surcharge de méthodes On réalise une surcharge de méthodes lorsque l'on déclare 2 méthodes de même nom mais avec des signatures différentes : par le nombre et/ les types de paramètres. Par contre, le type de retour doit être identique. On retrouve ce mécanisme lors de la définition de constructeurs et lors de l'implémentation de sous-classe (surcharge d'une méthode de la super-classe). Olivier Curé UMLV [page 124 ] Redéfinition ≠ surcharge On surcharge une méthode quand on garde le même nom et le même type de retour mais pas les mêmes paramètres dans la même classe ou sous-classes. Olivier Curé UMLV [page 125 ] Masquage de variables Une sous-classe peut redéfinir les variables portant le même nom que celles de sa super-classe. Une sous-classe peut accéder aux variables de sa super-classe à l'aide de casting ou bien de super. Olivier Curé UMLV [page 126 ] Retour sur le mot réservé : final Une classe déclarée final ne peut être étendue. De même, une méthode déclarée comme final ne peut être redéfinie. Enfin, une variable déclarée comme final ne peut être masquée. Olivier Curé UMLV [page 127 ] Classe abstraite Elle se trouve au sommet de la hiérarchie des classes. Elle définit l'interface des méthodes et ne peut être instanciée. Définir des méthodes abstraites dans une classe impose que la classe soit abstraite et que les sous-classes implémentent ses méthodes pour devenir concrètes. Une classe abstraite contient généralement au moins une méthode abstraite. Une méthode abstraite n'est pas implémentée. Olivier Curé UMLV [page 128 ] Exemple Classe abstraite abstract class GeometriePlane { static final double PI = 3.14159; abstract double perimetre(); abstract double surface(); } class Disque extends GeometriePlane { float rayon; public double perimetre() {return 2*GeometriePlane.PI*rayon;} public double surface() {return GeometriePlane.PI*rayon*rayon;} } class Rectangle extends GeometriePlane { float largeur, hauteur; public double perimetre() {return 2*(largeur+hauteur);} public double surface() {return largeur*hauteur;} } Olivier Curé UMLV [page 129 ] Interface Une interface Java (≠ interface graphique) est une classe où toutes les méthodes sont abstraites. Cette notion "remplace" l'héritage multiple car une classe peut implémenter plusieurs interfaces. Le mot clé abstract n'est pas utilisé. On ne peut pas instancier une interface. Définition d'une interface à l'aide de l'instruction interface. La sous-classe implémente une interface à l'aide de l'instruction implements. Olivier Curé UMLV [page 130 ] Exemple interface abstract class GeometriePlane { abstract double perimetre(); } interface Dessinable { public void dessiner(); } public class Rectangle extends GeometriePlane implements Dessinable { double largeur, hauteur; public double perimetre() {return 2*(largeur+hauteur);} public void dessiner() {....} } public class Disque extends GeometriePlane implements Dessinable { double rayon; public double perimetre() {return 2*Math.PI*r;} public void dessiner() {....} } Olivier Curé UMLV [page 131 ] Interface (2) On peut manipuler les rectangles et les disques comme des Dessinable à l'aide du polymorphisme : Dessinable formes[] = {new Disque(5), new Rectangle(2,3)}; for(int i = 0; i < formes.length; i++) { formes[i].dessiner(); } Une interface peut étendre une autre interface à l'aide de l'instruction extends. La hiérarchie des interfaces est différente de celle des classes. Dans la pratique, une interface ne peut contenir que des méthodes publiques et des attributs constants. Olivier Curé UMLV [page 132 ] Paquetage ou package Un paquetage regroupe un ensemble de classes (et interfaces) liées à un même domaine particulier (par exemple gestion des bases de données, accès au réseau, etc.). Les objectifs sont : - organisation cohérente des classes et interfaces. - facilite le développement de bibliothèques. - protection supplémentaire avec le mode protégé. Olivier Curé UMLV [page 133 ] Création d'un package Il faut ajouter en tête de l'unité de compilation (du fichier) package NomDuPackage; - indique à quel package appartient la (ou les) classe(s) du fichier. Exemple d'un package d'objets graphiques : package Graphics; interface Dessinable {...} class Disque {...} class Rectangle {...} class Cercle {...} Olivier Curé UMLV [page 134 ] Utilisation des classes d'un package Les classes (ou interfaces) d'un package peuvent être utilisées (importées) individuellement ou de manière globale (le package entier) par toute autre unité de compilation désirant les utiliser. Seules les classes déclarées publiques (public) dans le package sont accessibles. En dehors du package, les noms des classes sont : NomDuPackage.NomDeLaClasse. L'instruction import NomDuPackage permet d'utiliser (importer) les classes sans les préfixer par leur nom de package - si pas d'importation (import), il faut indiquer le nom complet de la classe NomDuPackage.NomDeLaClasse pour l'exploiter. Olivier Curé UMLV [page 135 ] Importation des packages et des classes 4 formes pour spécifier l'importation ● pas d'import : class TestImport1 { public static void main(String args[]) { java.awt.Point p = new java.awt.Point(1,2); } ● import package.comp1...compn; import java.awt : class TestImport2 { public static void main(String args[]) { awt.Point p = new awt.Point(1,2); } Olivier Curé UMLV [page 136 ] API : Interface de programmation des applications Core API regroupe un ensemble de classes prédéfinies d'usage général que l'on retrouve sur toutes les platesformes. ● Core API est découpée en plusieurs packages : java.applet : Gestion des applets java.awt : Gestion du fenêtrage et de son contenu (Cf. swing) java.io : Gestion des entrées-sorties et des fichiers java.lang : Gestion des types et des éléments de base du langage java.net : Gestion de la communication sur le réseau java.util : Structures de données et utilitaires java.rmi : Remote Method Invocation, appli. distribuée java.security : Signatures digitales, contrôle d'accès. ● Olivier Curé UMLV [page 137 ] Importation des packages et des classes (2) ● import package.comp1...compn.Class : import java.awt.Point; class TestImport3 { public static void main(String args[]) { Point p = new Point(1,2); import package.comp1...compn.*: } ● import java.awt.*; class TestImport4 { public static void main(String args[]) { Point p = new Point(1,2); Rectangle r = new Rectangle(); } Olivier Curé UMLV [page 138 ] Exception En Java, le traitement de certaines erreurs est automatique. Lorsqu'une méthode détecte une erreur, elle lève une exception. Celle-ci est équivalente à un signal ou à une interruption logicielle. Une exception est un objet Java (instance de la classe Exception) envoyé à la JVM. Olivier Curé UMLV [page 139 ] Principe des exceptions Le principe des exceptions en java est le suivant : ● toute méthode qui a un problème lève (throw) une exception . ● tout code qui appelle cette méthode doit attraper (catch) cette exception. ● la plupart des exceptions demandent à être "attrapées" faute de quoi le programme s'arrête en cours d'exécution. ● la recherche se fait en local, puis remonte la liste des appelants - acquittement de l'exception et reprise du code. ● Structures spécialisées : try {...} catch {...} Olivier Curé UMLV [page 140 ] Exploitation des exceptions Il est nécessaire de séparer le bloc d'instructions pouvant engendrer des erreurs. Ce bloc est insérer au niveau d'un try. Le(s) bloc(s) catch permet(tent) de récupérer la main pour traiter l'exception. On peut aussi utiliser ces blocs pour spécialiser les traitements. Olivier Curé UMLV [page 141 ] Exemple de gestion d'une exception try { x = System.in.read(); } catch (IOException e) { System.out.println("Erreur : " + e.getMessage()); } Olivier Curé UMLV [page 142 ] 5. Collections dans Java Olivier Curé UMLV [page 143 ] Présentation générale ● ● ● Une collection est un objet qui contient d'autres objets. Ces objets proposent une solution au stockage de données et permettent une manipulation de celles-ci Les classes et interfaces se trouvent dans le paquetage : java.util. Olivier Curé UMLV [page 144 ] Collections et versions de Java ● ● Premières versions de Java : – Tableaux – Vector : tableaux dynamiques (listes) – Hashtable : tables associatives A partir de Java2, existence d'une infrastructure pour la gestion de collections ( dans le package java.util). Olivier Curé UMLV [page 145 ] Infrastructure ● ● Offre une architecture unifiée pour représenter et manipuler les collections. Composée de 3 parties : – Une hiérarchie d'interfaces permettant de représenter les collections sous forme de types abstraits. – Des implémentations de ces interfaces. – Implémentation de méthodes liées aux collections (recherche, tri, etc.). Olivier Curé UMLV [page 146 ] Avantages ● Les collections permettent de : – Améliorer la qualité et la performance des applications – Réduire l'effort lors de l'implémentation – Faciliter l'apprentissage de nouvelles API – Réduire le coût de conception de nouvelles API – Encourager le réutilisation de logiciels. Olivier Curé UMLV [page 147 ] Interfaces ● 2 hiérarchies principales : – Map : collections indexées par des clés (Cf. Entrées d'un dictionnaire) – Collection Olivier Curé UMLV [page 148 ] Classes ● ● Abstraites : AbstractCollection, AbstractMap, AbstractList, ... Concrètes : ArrayList, HashSet, TreeSet, HashMap, ... Elles héritent des classes abstraites Olivier Curé UMLV [page 149 ] Interface Collection ● Un objet qui est un groupe d'objets ● Principales méthodes : ● boolean add(Object obj) ● boolean contains(Object obj) ● boolean containsAll(Collection collection) ● Iterator iterator() ● int size() ● Object[] toArray() ● Object[] toArray(Object[] tableau) Olivier Curé UMLV [page 150 ] Interface Set ● ● Un groupe d'objets n'acceptant pas 2 objets égaux (au sens de equals). Implémentations : – HashSet garantit un temps constant pour les opérations de base (set, size, add, remove). – TreeSet garantit que les éléments sont rangés dans leur ordre naturel (interface Comparable) ou l'ordre d'un Comparator. Olivier Curé UMLV [page 151 ] Interface List ● ● ● Un groupe d'objets repérés par des numéros (en débutant à l'indice 0). Classes implémentées : ArrayList (tableau à taille variable), LinkedList (listechaînée) En règle générale, on utilise ArrayList maisLinkedList est utile si il y a beaucoup d'opérations d'insertions/suppressions (evite les décalages). Olivier Curé UMLV [page 152 ] Classe ArrayList ● ● ● Une sorte de tableau contenant un nombre quelconque d'instances de la classe Object (utiliser Integer pour ranger des entiers). Les emplacements sont repérés par des valeurs entières (à débutant à 0, comme un tableau). Les méthodes ne sont pas synchronisées (Vector). Olivier Curé UMLV [page 153 ] Méthodes de ArrayList boolean add(Object obj) ● void add(int indice, Object obj) ● boolean contains(Object obj) ● Object get(int indice) => casting l'élément. ● int indexOf(Object obj) ● Iterator iterator() ● void remove(int indice) ● void set(int indice, Object obj) ● int size() ● Olivier Curé UMLV [page 154 ] Exemple d'ArrayList ArrayList liste = new ArrayList(); Personne p1 = new Personne("Toto"); liste.add(p1); // création d'autres instances de Personne for (int cpt=0; cpt<liste.size();cpt++) System.out.println(((Personne)liste.get(cpt)).getNom( )); } Olivier Curé UMLV [page 155 ] Interface Iterator ● ● Une interface permettant d'énumérer les éléments contenus dans une collection. Toutes les collections proposent une méthode itérator renvoyant un itérateur. Olivier Curé UMLV [page 156 ] Méthodes d'Iterator ● boolean hasNext() ● object next() – Lance une exception NoSuchElementException lorsqu'il n'y a plus rien à renvoyer. Olivier Curé UMLV [page 157 ] Exemple d'Iterator ArrayList liste = new ArrayList(); Personne p1 = new Personne("Toto"); liste.add(p1); // création d'autres instances de Personne Iterator it = liste.iterator(); while(it.hasNext()) { System.out.println(((Personne)it.next()).getNom()); } Olivier Curé UMLV [page 158 ] Exemple d'Iterator (2) ArrayList liste = new ArrayList(); Personne p1 = new Personne("Toto", "Marie"); liste.add(p1); // création d'autres instances de Personne Iterator it = liste.iterator(); while(it.hasNext()) { Personne tmp = (Personne)it.next(); System.out.println(tmp.getNom()+" "+tmp.getPrenom()); } Olivier Curé UMLV [page 159 ] Interface Map ● Des couples clé-valeur. ● Une clé repère une unique valeur. ● Implémentations : – HashMap : table de hachage avec garantie d'un accès en temps constant. – TreeMap : arbre ordonnée* suivant les valeurs des clés (accès en log(n)). * ordre naturel ou une instance de Comparator. Olivier Curé UMLV [page 160 ] Méthodes de Map ● boolean containsKey(Object clé) ● boolean containsValue(Object valeur) ● Set entrySet() ● Object get(Object clé) // null si objet n'existe pas. ● boolean isEmpty() ● Set keySet() ● int size() ● Collection values() Olivier Curé UMLV [page 161 ] Table de hachage ● ● ● ● Une table de hachage range des éléments en les regroupant dans des sous-ensembles pour les retrouver plus rapidement. Le regroupement dépend de la valeur d'un calcul effectué sur les éléments. On retrouve l'élément en fournissant la valeur. Recherche efficace si répartition uniforme des éléments sur les sous-ensembles. Olivier Curé UMLV [page 162 ] Classe HashMap ● ● Utilise la structure d'une table de hachage pour ranger les clés. La méthode hashCode() est exploitée pour répartir les clés dans la table de hachage. Olivier Curé UMLV [page 163 ] Exemple de HashMap Map hm = new HashMap(); Personne p1 = new Personne("Toto"); p1.setMatricule("p99"); hm.put(p1.getMatricule(), p1); . . // création d'autres instances de Personne Personne p2 = (Employe)hm.get("p101"); Collection elements = hm.values(); Iterator it = elements.iterator(); while (it.hasNext()) { System.out.println( ((Personne)it.next()).getNom()); } Olivier Curé UMLV [page 164 ] Trier une liste import java.util.*; public class Coll1 { public static void main(String args[]) { List liste = new ArrayList(); liste.add( new Integer(9)); liste.add(new Integer(12)); liste.add(new Integer(5)); Collections.sort(liste); Iterator it = liste.iterator(); while (it.hasNext()) { System.out.println( ((Integer)it.next()).toString()); } } } Olivier Curé UMLV [page 165 ] Recherche dans une liste import java.util.*; public class ListePersonneTest { public static void main(String[] args) { List liste = new ArrayList(); Personne p1 = new Personne("Xyel","Pierre"); Personne p2 = new Personne("Durand","jean"); Personne p3 = new Personne("Smith","Joe"); liste.add(p1); liste.add(p2); liste.add(p3); Collections.sort(liste, new ComparatorPersonne()); System.out.println("Recherche ="+ Collections.binarySearch(liste,p1,new ComparatorPersonne())); } } // Exécution : Rercherche = 2. Olivier Curé UMLV [page 166 ] Interface Comparator ● Elle propose une méthode : – int compare(Object o1, Object o2) Elle doit renvoyer : – Un entier positif si o1 est "plus grand" que o2. – 0 si la valeur de o1 est identique à celle de o2. – Une entier négatif si o1 est "plus petit" que o2. Olivier Curé UMLV [page 167 ] Exemple d'un Comparator import java.util.Comparator; public class ComparatorPersonne implements Comparator { public int compare(Object o1, Object o2) { String nom1 = ((Personne) o1).getNom(); String nom2 = ((Personne) o2).getNom(); return nom1.compareTo(nom2); } } Olivier Curé UMLV [page 168 ] Utilisation d'un Comparator import java.util.* public class ListePersonneTest { public static void main(String[] args) { List liste = new ArrayList(); Personne p1 = new Personne("Xyel","Pierre"); Personne p2 = new Personne("Durand","jean"); Personne p3 = new Personne("Smith","Joe"); liste.add(p1); liste.add(p2); liste.add(p3); Collections.sort(liste, new ComparatorPersonne()) } } Olivier Curé UMLV [page 169 ]