Objectifs du cours: Classes améliorées CSI1502: Comprendre les implications de: Références et alias d’objets différents Passer des objets (par référence) comme paramètres Le mot clé static: Variables et méthodes statiques Classes encapsulant les types de données primitifs Classes incorporées et classes internes Interfaces en génie logiciel Composants de la GUI, boite de dialogue, événements et listeners . Introduction au génie logiciel Chapitre 5: Classes améliorées 2 Plus d’infos sur les références La référence null. Rappelez-vous (chapitre 2) qu’une référence d’objet contient l’adresse mémoire de l’objet. Plutôt que de considérer des adresses arbitraires, nous décrivons graphiquement les références comme des pointeurs vers des objets. ChessPiece bishop1 = new ChessPiece(); bishop1 Une référence d’objet ne pointant vers aucun objet est appelée une référence nulle. Essayer d’accéder à l’objet d’une telle référence cause la levée d’une exception NullPointerException . Par exemple: String name; déclare une référence vers un objet (de type String) mais ne crée pas d’objet String.Ainsi cette référence ne référe à aucun objet. Donc la variable name contient une référence nulle. 3 4 La référence this La référence this La référence this permet à un objet de s’autoréférer. A l’intérieur d’une méthode, la référence this référe à l’objet en train d’être exécuté. Par exemple: if(this.position == piece2.position) result = false; précise quelle variable position est en train d’être manipulée. La référence this référe à l’objet par l’intermédiaire duquel la méthode contenant le code a été appelée. 5 La référence this peut aussi servir à distinguer les paramètres d’un constructeur des variables correspondantes de l’objet avec des noms semblables. A éviter pour cause de problèmes de lisibilité. Public Account (Sring name, long acctNumber, double balance) { this.name = name; this.acctNumber = acctNumber; this.balance = balance; } 6 1 Affectations reparcourues Object Reference Assignment Affecter consiste à copier une valeur et à stocker cette copie dans une variable. Pour les références d’objets, l’affectation copie d’adresse mémoire : bishop2 = bishop1; Pour les types de données primitifs: num2 = num1; Avant Après bishop1 num1 num2 num1 num2 5 12 5 5 Après Avant bishop2 bishop1 bishop2 7 8 Que sont les alias? Test d’égalité pour les objets Plusieurs références pointant vers le même objet sont des alias du même objet. L’opérateur == compare les références d’objets et retourne true si les références sont des alias d’un même objet. Une méthode est définie pour tous les objets, mais à moins d’avoir été redéfinie lors de l’écriture d’une classe, cette méthode demeure identique en action à l’opérateur ==. Un objet et ses données peut donc être accédés grâce aux différents alias de l’objet. bishop1.equals(bishop2); Les alias sont utiles, mais doivent être gérés avec précautions. retourne true si les deux références pointent vers le même objet. On peut redéfinir la méthode equals pour toutes conditions d’égalité jugées pertinentes. Modifier l’état d’un objet affecte l’état de tous ses alias ! 9 10 Passage d’objets en tant que paramètres Le Ramasse-miettes en Java Quand un objet n’est plus référencé par aucune référence, celui-ci ne peut plus être accéder par le programme. Il est donc inutile et peut être considéré comme un déchet (garbage). Java effectue efface périodiquement de sa mémoire ces déchets. Ce processus, appelé ramasse-miettes, permet de recycler la mémoire des objets déréférencés. 11 Les paramètres de méthode en Java sont passés par valeur. Ceci signifie qu’une copie du vrai paramètre (valeur passée) est stockée dans le paramètre formel (argument de la méthode). Passer des paramètres revient essentiellement à effectuer des affectations. Quand un objet est passé à une méthode, le paramétre réel et le paramètre formel deviennent des alias du même objet. 12 2 Passer des objets aux méthodes ParameterPassing.java Ce que vous effectuez avec un paramètre à l’intérieur d’une méthode peut éventuellement avoir des conséquences permanentes (en dehors de la méthode). ParameterPassing.java (page 277) ParameterTester.java (page 279) Num.java (page 281) public class ParameterPassing { // sets up 3 variables and illustrate parameter passing public static void main (String [] args) { ParameterTester tester = new ParameterTester(); int a1 = 111; Num a2 = new Num (222); Num a3 = new Num (333); System.out.println("Before ChangeValues: "); System.out.println("a1 a2 a3: " + a1 + " " + a2 + " " + a3); Remarquez la différence entre modifier la référence et modifier l’objet pointé par la référence. tester.changeValues(a1, a2, a3); } 13 } ParameterTester.java 14 Num.java public class Num { private int value; public class ParameterTester { public void changeValues(int f1, Num f2, Num f3) { System.out.println("Before changing the values: "); System.out.println("f1 f2 f3: " + f1 + " " + f2 + " " + f3); // Constructor public Num (int update) { value = update; } f1 = 999; f2.setValue(888); f3 = new Num(777); } System.out.println("After ChangeValues: "); System.out.println("a1 a2 a3: " + a1 + " " + a2 + " " + a3); // set up a value public void setValue(int update) { value = update; } System.out.println("After changing the values: "); System.out.println("f1 f2 f3: " + f1 + " " + f2 + " " + f3); // toString public String toString() { return value + " "; }} } 15 16 Que sont les variables statiques? Les résultats: passage de paramètres Avant ChangeValues: a1 a2 a3: 111 222 333 Before changing the values: f1 f2 f3: 111 222 333 Associées à une classe et non à un objet. Les variables statiques peuvent être appelées variables de classe. Normalement chaque objet a son propre espace mémoire Si une variable est déclarée statique, une seule copie de la variable existe. private static float price; After changing the values: f1 f2 f3: 999 888 777 Après ChangeValues: a1 a2 a3: 111 888 333 17 L’espace mémoire pour une variable statique est créé quand la classe la déclarant est chargée. Tous les objets de la classe ont accès aux variables statiques de la classe Æ Modifier la valeur d’une variable statique modifie sa valeur dans toutes les instances de la classe. 18 3 Plus d’infos sur les méthodes statiques Plus d’infos sur les méthodes statiques :un exemple Les méthodes statiques aussi nommées méthodes de classe sont appelées par l’intermédiaire du nom de classe plutôt qu’à travers un objet particulier. Par exemple , les méthodes de la classe Math sont statiques. Pour créer une méthode statique, nous définissons la méthode à l’aide du mot clé static . Les méthodes statiques ne peuvent utiliser des variables d’instance, les variables d’instance n’étant créées qu’une fois les objets instanciés. class Helper public static int triple (int num) { int result; result = num * 3; return result; } public static int abs(int num); Puisqu’étant statique, statique, la méthode peut être appelée ainsi: ainsi: value = Helper.triple (5); 19 Méthodes statiques and variables: CountInstances.java 20 Méthodes statiques and variables: Slogan.java public class Slogan { private String phrase; public static int count = 0; public class CountInstances { public static void main ( String[] args) { Slogan obj; // the constructor public Slogan (String str) { phrase = str; count++; } obj = new Slogan("Hello world"); obj = new Slogan("Talk is cheap."); obj = new Slogan("Don't worry, be happy."); System.out.println("Slogans created: " + Slogan.getCount()); } } 21 Que sont les classes encapsulantes? } // returns the number of objects of this class created public static int getCount() { return count; } 22 Quelques méthodes de la classe Integer : voir p.287 Une classe encapsulante représente un certain type de données primitif. Par exemple Integer ageObj = new Integer (20); Integer (int value) // constructeur: crée un nouveau objet Integer utilise la classe Integer pour créer un objet représentant l’entier 20. Pourquoi ceci ? Ceci est utile lorsque le programme requiert un objet et non un type de données primitif Chaque type de données primitif (TDP) est encapsulé par de telles classes. Ces classes sont situées dans le package Java.lang, voir TDP Figure 5.4 Wrapper Class byte Byte int Integer char Character, etc. pour les autres TDPs 23 byte byteValue () double doubleValue () // retourne la valeur de cette objet dans le TDP correspondant static int ParseInt (String str) // retourne l’int correspondant à la valeur stockée dans la chaîne de caractères. static String toBinaryString (int num) // retourne une chaîne de caractères représentant l’entier dans la base correspondant à num. 24 4 Java I/O Entrées à partir du clavier … Les entrées / sorties sont effectués en java par l’intermédiare d’objets représentant des flux de données. Un flux est une suite ordonnée d’octets Les entrées peuvent être lues à partir du clavier sans avoir à utiliser les classes Keyboard et Wrapper. Voir Wages2.java (page 289): Plus au chapitre 8 import java.io.*; L’objet System.out représente un flux standart de sortie, qui est par défaut l’écran. … Lire à partir du clavier est plus compliqué… Æchapitre 8. … BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String name = in.Readline(); int hours = Integer.parseInt(in.readLine()); 25 26 Enclosing Class Classes imbriquées Classes Imbriquées Nested Class En plus de contenir des données et méthodes, les classes peuvent contenir d’autres classes dite imbriquées. Une classe imbriquée a accès aux variables et méthodes de la classe dans laquelle elle se trouve, même si celles-ci sont déclarées privées. Ceci est une relation spéciale et doit être utilisé de manière adéquate. Une classe imbriquée produit son propre bytecode . Si une classe nommée Inside est déclarée dans une classe nommée Outside, 2 bytecodes seront produits Outside.class Outside$Inside.class Les classes imbriquées peuvent être déclarées statiques, dans lequel cas elles ne peuvent référer aux variables et méthodes d’instance. 27 Classes internes: classes imbriquées non statiques 28 Classes imbriquées: Outer.java Une classe interne est associée à chaque instance de la classe dans laquelle elle est imbriquée, et ne peut exister que le temps d’instanciation de cette dernière. public class TestInner { // create and manipulate an outer object public static void main (String[] args) { Outer out = new Outer(); public class Outer { private int num; private Inner in1, in2; public Outer() { num = 2365; in1 = new Inner ("Hello"); in2 = new Inner ("Hello again"); } public void changeMessage() { in1.message = "Eat desert first"; in2.message = "Another miracle"; } System.out.println(out); out.changeMessage(); System.out.println(out); } } 29 public String toString() { return in1 + "\n" + in2; } Continued…30 5 Classes imbriquées : Outer.java Classes imbriquées : En sortie Hello Outer number = Hello again Outer number = Eat desert first Outer number = Another miracle Outer number = // The inner class private class Inner { public String message; public Inner (String str) { message = str; } public String toString() { num++; return message + "\nOuter number = " + num; } 2366 2367 2368 2369 } } 31 32 Les interfaces: une utilité architecturale pour le programme interface est un mot clé Interfaces Aucune de ces méthodes n’a été définie (corps de fonction) fonction) public interface Doable { public void doThis(); public int doThat(); public void doThis2 (float value, char ch); public boolean doTheOther (int num); } Une interface Java est un ensemble de méthodes abstraites et de constantes Une méthode abstraite est une méthode dont ne figure que la déclaration. Une méthode abstraite peut être déclarée en utilisant le mot-clé abstract, mais ceci reste facultatif dans une interface (une interface ne comprenant par définition que des méthodes abstraitres) Une interface est utilisée pour définir formellement un ensemble de méthode qu’une classe devra implémenter. Un pointpoint-virgule suivant la déclaration de chaque méthode. méthode. 33 34 Interfaces: Un exemple public class CanDo implements Doable { public void doThis () { // whatever } Plus d’infos sur les interfaces implements est un mot clé public void doThat () { // whatever } Toute méthode listée dans Doable est implémentée // etc. Une interface ne peut être instanciée. Les méthodes d’une interface sont par défaut publiques. Une classe implémente formellement une interface en: Lq déclarant dans l’en-tête de la classe. Fournissant les implémentations de chaques méthodes déclarées dans l’interface. Si une classe déclare implémenter une interface, toutes les méthodes de l’interface doivent être implémentées, sinon il y aura des erreurs de compilation. En plus de méthodes abstraites, une interface peut contenir des constantes. Quand une classe implémente une interface, elle a accès à toutes les constantes de cette dernière. } 35 36 6 Interfaces Interfaces suite… Une classe implémentant une interface peut toujours implémenter d’autres méthodes Une classe peut implémenter de plusieurs interfaces class ManyThings implements interface 1, interface2, interface3 { // all methods of all interfaces } Les interfaces implémentées sont listées dans la clause suivant implements, séparées par des virgules. La classe doit implémenter obligatoirement toute les méthodes de toutes les interfaces listées. La bibliothèque standard Java contient plusieurs interfaces utiles. L’interface Comparable contient une méthode abstraite nommée compareTo, qui est utilisée pour comparer des objets. La classe String implémente Comparable, ce qui nous permet de classer les chaînes de caractères en ordre alphabétique. L’interface Iterator contient des méthodes permettant à l’utilisateur de parcourir aisément un ensemble d’objets. 37 38 L’ interface iterator L’interface comparable L’interface Comparable fournit un mécanisme commun pour comparer 2 objets if (obj1.compareTo(obj2) < 0) System.out.println (“obj1 is less than obj2”); Le résultat est négatif si obj1 est inférieur à obj2, 0 s’ils sont égaux et positif si obj1 est supérieur à obj2. L’interface Iterator fournit un moyen de parcourir un ensemble d’objets un par un. La méthode hasNext renvoie un résultat booléen (true s’il reste des éléments à traiter) La méthode next renvoie un objet. La méthode remove supprime l’objet renvoyé par la méthode next. 39 40 GUIs et fenêtres de dialogue (approfondissements au Chapitre 9) Qu’est-ce qu’une fenêtre de dialogue? Une interface graphique utilisateur -Graphical User Interface (GUI)est créée avec au moins trois sortes d’objets. Composants Événements listeners Un composant GUI définit un élément d’écran pour afficher une information ou pour permettre à l’utilisateur d’interagir avec le programme (boutons à presser, champs textuels,etc…). Le package Swing contient une classe nommée JOptionPane qui simplifie la création, l’utilisation de fenêtres de dialogues élémentaires. Un composant graphique utilisé pour intéragir avec l’utilisateur. Une fenêtre de message affiche une chaîne de caractères. Une fenêtre de dialogue affiche une invite de commande et un espace de saisie. Une fenêtre de confirmation présente une question “oui-ou-non” à l’utilisateur. PUSH ME! 41 42 7 Au sujet des Events et Listeners Les interfaces Listener Event Générateur Listener Cet objet est susceptile de générer un événement. événement. Cet objet attend et traite les événements. événements. Quand un événement est créé, créé, le générateur appelle la méthode appropriée du listener, passant en paramètre un objet décrivant l’événement. l’événement. 43 Un event listener : PushCounter.java (un extrait) 44 Sommaire: Classes améliorées Comprendre les implications de: Références et alias d’objet différents Passer des objets (par référence) comme paramètres Le mot clé static: Variables et méthodes statiques Classes encapsulant les types de données primitifs Classes incorporées et classes internes Interfaces en génie logiciel Composants de la GUI, boite de dialogue, événements et listeners . import hava.awt.*; import java.awt.event.*; import javax.swing.*; public class PushCounter extends JApplet { private int pushes … public void int () { pushes = 0; push = new JButton(“PUSH ME!”); push.AddActionListener(new ButtonListener()); … } PUSH ME! On peut créer un objet listener en écrivant une classe implémentant une interface listener donnée. Pour exemple, l’interface MouseListener contient des méthodes correspondant aux événements souris. Après avoir créé le listener, nous ajoutons celui-ci au composant qui pourrait générer un événement pour lier formellement la source d’événements au listener. Voir PushCounter.java à la p.305 45 46 8