Programmation Objet en JAVA Mise à Niveau Alexandre Allauzen (Université Paris-Sud / LIMSI-CNRS) allauzen@limsi.fr Ce cours reprend en partie le matériel pédagogique mis au point par Claude Barras et Frédéric Vernier et s'inspire du cours de Philippe Genoud (INRIA)
Introduction à la P.O.O Programmation fonctionnelle Des fonctions et leurs résultats Programmation impérative ou procédurale Des ordres (éventuellement avec des fonctions) Algorithmes + Structures de données = Programmes Programmation Orientée Objet (POO) Un programme est divisé en plusieurs modules (objets) indépendants. Les modules sont chargés en mémoire à l’exécution. Le concepteur fait évoluer ses modules en parallèle et ensemble. Méthodes + Données = Objet Les modules sont typés comme des int et des float Le type de module est aussi important que le module lui-même Le type d'un objet est sa classe
Les principes de la POO Permettre la description d'un problème à l'aide de termes liés au problème et non à la machine : par l'identification et la définition des concepts et des objets, par la mise en oeuvre de leurs interactions Tout est objet. Il contient ses données (attributs), et possède une interface (méthodes publiques) permettant de lui adresser des requêtes (ou des messages) Un programme est un ensemble d'objets qui communiquent entre eux (envoi de message). Chaque objet est construit à partir d'autres objets et possède sa mémoire propre. Un objet a un type. Il est l'instance d'une classe. Les objets d'un même type peuvent recevoir les mêmes messages. La distinction la plus importante entre objets de classes différentes est « quels messages peut-on lui envoyer ? »
package dir1.dir2.mypackage; Le package Un package = regroupement cohérent de classes. import java.util.*;// invoque toutes les classes //du package import java.util.ArrayList; //uniquement 1 classe Pour constituer un package : L'utilisation se fait soit via import soit comme ceci : Mettre toutes les classes d'un même package dans un même répertoire -> mypackage Attention aux noms utilisés. package dir1.dir2.mypackage; Indique le chemin pour trouver les fichiers .class à partir du CLASSPATH package mypackage; public class MyClass{...} mypackage.MyClass m = new mypackage.MyClass();
Exemple 1 Attributs Méthodes public class etudiant { String nom; int promo, note; String traiterExam(String enonce) {…} } public class prof { String faireSujetExam() int corrigerExam(String copie) Attributs Méthodes
Exemple 1 - suite Public class GestionDuL3 { public static void main(String[] args) { etudiant e = new etudiant(); e.nom = «Jean-Louis Ezine»; e.promo = 2; prof p = new prof(); String ennonce = « Premier exercice … »; e.note=p.corrigerExam(e.traiterExam(ennonce)); … e.nom=«Gabriel Paoli»; e.nom=«vqdfgsfkbqdlkjfgh»; e.note = -324; }
Principe d'encapsulation - Rappel Un objet = données (attributs) + algorithmes (méthodes) Principe d'encapsulation : L'accès aux données (privées) ne peut se faire que par l'intermédiaire de l'interface (méthodes publiques). Les modifications des structures de données n'affectent pas les programmes qui utilisent l'objet. Réutilisation.
Concepts Objet : en mémoire La classe est chargée une seule fois (partie static) Les instances sont chargées dynamiquement autant de fois qu’il y a d’instances dans le programme Un compteur est créé pour chaque instance A chaque fois qu’une nouvelle variable fait référence à l’instance compteur++ A chaque fois qu’une référence est perdue (sortie de boucle/bloc) compteur- - Quand (compteur==0), la JVM libère la mémoire Quand la JVM libère la mémoire d’un objet, compteur- - pour les attributs de l’instance détruite ! Si dernière référence => destruction en chaîne Si co-référence : problème !
Concepts Objet : en pratique Attention à la terminologie Classe / Instance c’est clair Objet = moins clair, pourtant c’est le terme le plus utilisé Méthode = une fonctionnalité interne / externe privée / publique Variable d'instance : Variable typée (primitif ou objet) Liée à un objet Variable de classe Partagée par toutes les instances de la classe (mot clé static) Objet = données + méthodes Programmation Objet = Définir, implémenter si besoin les types d'objet : les classes nécessaires Création d'un ensemble d’objets Mise en interaction des objets
Sondage : Manipulation des données En java : Comment sont manipulés les objets, les tableaux, les types primitifs ? Comment sont passés les paramètres des méthodes ?
Méthodes statiques : Passage des paramètres public static void echange(int a , int b) { int tmp = a ; a = b; b = tmp; } public static void echange(Integer a, Integer b) { Integer tmp = a; System.out.println("dedans :" + a + " " + b); public static void main(String[] args) { Integer a = new Integer(3); Integer b = new Integer(4); int x = 3; int y = 4; echange(x,y); System.out.println("Après 1:" + x + " " + y); echange(a,b); System.out.println("Après 2:" + a + " " + b); Le passage des paramètres se fait par valeur. Les 2 méthodes echange n'ont pas la même signature : surcharge Après 1:?? Après 2:??
Passage par valeur -1 Appel de la méthode : var @ val aObjet #0 #a bObjet #1 #b x #2 3 y #3 4 public static void echange(int a , int b) { int tmp = a ; a = b; b = tmp; } public static void echange(Integer a, Integer b) { Integer tmp = a; System.out.println("dedans :" + a + " " + b); public static void main(String[] args) { Integer aObjet = new Integer(3); Integer bObjet= new Integer(4); int x = 3; int y = 4; echange(x,y); System.out.println("Après 1:" + x + " " + y); echange(aObjet,bObjet); System.out.println("Après 2:" + a + " " + b); Appel de la méthode : var @ val a #55 3 b #57 4
Passage par valeur -2 Appel de la méthode : var @ val aObjet #0 #a bObjet #1 #b x #2 3 y #3 4 public static void echange(int a , int b) { int tmp = a ; a = b; b = tmp; } public static void echange(Integer a, Integer b) { Integer tmp = a; System.out.println("dedans :" + a + " " + b); public static void main(String[] args) { Integer aObjet = new Integer(3); Integer bObjet= new Integer(4); int x = 3; int y = 4; echange(x,y); System.out.println("Après 1:" + x + " " + y); echange(aObjet,bObjet); System.out.println("Après 2:" + a + " " + b); Appel de la méthode : var @ val a #78 #a b #79 #b
Mais pourquoi ? > java Test Avant 2 Apres 2 Apres 0 public class Test{ public static void annule(int a ){ a = 0; } public static void annule(int tab[] ){ tab[0]=0; public static void main(String[] args) { int[] tab = { 2, 5, -1, 4, 3 }; System.out.println("Avant "+ tab[0]); annule(tab[0]); // Test.annule(tab[0]) System.out.println("Apres "+ tab[0]); annule(tab); }; > java Test Avant 2 Apres 2 Apres 0 var @ val tab #x 2 #x+1 5 #x+2 -1 ...
Exemple de classe type - 1 public class Etudiant { public String nom; public int promo; // Les constructeurs Etudiant(){ nom = « Toto »; promo = 0; } public String traiterExam( String enonce){…} public class AdminFac { public static void main(String[] args){ Etudiant et = new Etudiant(); et.nom = Robert; et.promo = 5; } Et le principe d’encapsulation ! N’importe qui peut “modifier” un étudiant comme il veut !
Exemple de classe type - 2 public class Etudiant { // les attributs sont privés private String nom; private int promo; // Les constructeurs Etudiant(String n, int p){ nom = n; promo = p; } public String traiterExam(String enonce){…} public class AdminFac { public static void main(String[] args){ Etudiant et = new Etudiant( “Robert”,5); } Comment connaître le nom d’un étudiant ? Un étudiant peut-il changer de promo ? de nom ?
Exemple de classe type - 3 public class Etudiant { // les attributs sont privés private String nom; private int promo; // Les constructeurs Etudiant(){ nom = « Toto »; promo = 0; } Etudiant(String n, int p){ nom = n; promo = p; Et tout le monde peut modifier la promo ? // L'interface : ici les // assesseurs “setter & // getter” public String getNom(){ return nom; } public int getPromo(){ return promo; public void setPromo(int p){ promo = p; // et les algo nécessaires. public String traiterExam( String enonce){…}
Définition des accès Les droits d’accès se font lors de la définiton d’une classe Sondage d’opinion : public ? private ? « friendly package access » ? protected ?
Définition des accès Dans un objet l'accès et l'utilisation d'un attribut ou d'une méthode est contrôlé : public : tout le monde peut y accéder, entre autre un utilisateur, le « client programmeur ». Définit l'interface de la classe. private : accès interne à l'objet Selon le principe d'encapsulation, les attributs doivent être « private » le « friendly package access » : public pour les classes du même package protected : public pour les classes qui héritent (nous y reviendrons plus tard) + friendly.
Droits d’accès, exemples package licence; public class Etudiant { // les attributs sont privés private String nom; public int promo; // Les constructeurs Etudiant(String n, int p){ nom = n; promo = p; } public String traiterExam(String enonce){…} private String tricherVoisin(){...}; package exam; public class Exemple { public static void main (...){ Etudiant e = new Etudiant(“Toto”,2); e.promo = 3; e.nom = “Titi”; String reponse = e.traiterExam(“...”); reponse = e.tricherVoisin(); }
Notions de Programmation OO Responsabilités Chaque objet est responsable de l'accomplissement des tâches qui lui sont associées. Les objets clients envoient des messages aux objets serveurs. Eléments « atomiques » Les éléments de base sont des objets qui sont des instances d'une classe Les propriétés génériques d'un objet sont au niveau de la classe L'état d'un objet est décrit au niveau de l‘instance Les classes sont organisées hiérarchiquement et bénéficient d'un mécanisme d'héritage automatique.
Plan Pour aujourd’hui : un sondage principe fondateur de Java classe et objet, encapsulation constructeur
Constructeurs – 1 Des méthodes permettant de construire et préparer l'objet à être utiliser : Construction et initialisation selon les souhaits du programmeur Si aucun constructeur est défini alors il existera un constructeur par défaut qui initialise les variables à leurs valeurs par défaut : NomClasse() Si une classe a un constructeur, il n'y a plus de constructeur par défaut On cependant peut définir son constructeur par défaut. Il peut y avoir plus d'un constructeur par classe avec des signatures différentes public class MaClass { /* Les attributs */ /* Les constructeurs */ public MaClass(String nom){...} public MaClass(String nom,int nb) {...} /* L'interface */ /* Les méthodes privées */ public static void main(String[] args){ /* MaClass mc=new MaClass(); * c'est interdit ! */ String n = “un nom” ; int i = 5; // par contre MaClass mc1=new MaClass(n); MaClass mc2=new MaClass(n,i); }
Par contre public class MaClass { /* Les attributs */ /* Les constructeurs */ public MaClass(String nom){...} public MaClass(String nom,int nb){...} public MaClass(){...} /* L'interface : les méthodes public */ /* Les méthodes privées */ public static void main(String[] args){ MaClass mc1=new MaClass(); * c'est possible ! */ String n = “un nom” ; int i = 5; // et aussi MaClass mc1=new MaClass(n); MaClass mc2=new MaClass(n,i); }
Constructeurs – 2 Conseil : Lors de la création d’une classe : éviter le constructeur par défaut Un constructeur doit initialiser proprement tous les attributs L’objet construit doit être prêt à l’emploi. Utiliser l’IDE. Indispensable avec le principe d'encapsulation ! L'opérateur new permet de Charger les méthodes de la classe en mémoire si c’est la première fois qu’un objet de ce type est invoqué Créer l’instance en mémoire (Réserve exactement la taille de mémoire pour les données et les initialise avec leur valeurs par défaut) Lancer le constructeur (Correspondant aux arguments donnés) Le constructeur peut appeler d’autres méthodes de l’instance (y compris d’autres constructeurs) ou de la classe.
mauvais exemple Que vaut c1.rayon ? Que vaut c1.centre ? import java.awt.*; public class CercleNul { private Point centre; private float rayon; private Color color; public Point getCentre() { return centre; } public float getRayon() { return rayon; public static void main( String[] args) { /* construction par défaut */ CercleNul c1 = new CercleNul(); System.out.println(c1.getCentre()); Que vaut c1.rayon ? Que vaut c1.centre ?
mauvais exemple - 2 : unPoint import Point;// on a besoin de la classe Point ! public class TestPoint { public static void main(String[] arg) { Point unPoint = new Point();// une variable objet unPoint.setX(10); unPoint.setY(100); System.out.println("point\n\t d'abscisse " + unPoint.getX() + "\n"+"\t et d'ordonnée "+ unPoint.getY()); } }// Fin class TestPoint
Notion de surcharge Plusieurs méthodes de même nom mais de signatures différentes (liste d'arguments + type de retour). public Etudiant(String unNom, int unePromo) { nom = unNom; promo = unePromo; } public void Etudiant(String unNom) { promo = 0; La surcharge du constructeur permet une initialisation explicite des variables d'instance. Un constructeur par défaut est un constructeur sans argument. public Etudiant() { nom = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
Auto-Référence (this) Dans une méthode, le mot-clé this fait référence à l'objet sur lequel opère la méthode. System.out.println( this ); On peut imprimer toute instance en JAVA. L'impression fait appel à la méthode toString() (héritée de Object). Dans un constructeur, le mot-clé this en début d'un constructeur désigne un autre constructeur de la même classe. public Etudiant() { this( "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ); } À consommer avec modération ! Et avec le constructeur ??
Reprenons : la classe Une classe décrit, définit, implémente un type d'objet : ses attributs et ses méthodes son interface (public) et sa partie private. Elle doit être utilisable, réutilisable, évolutive : principe d'encapsulation interface bien pensée Une classe est un modèle de définition pour des objets ayant même structure (même ensemble d'attributs), même comportement (mêmes opérations, méthodes), une sémantique commune. Une classe n'est pas un objet. Un objet est l'instanciation d'une classe (et une seule), une représentation dynamique, « vivante ».
Reprenons : l'objet Un objet est l'instanciation d'une seule classe. conforme par construction au « modèle » : constructeur. Chaque objet est unique : son espace mémoire, ses attributs propres et donc son état sa référence Un objet se manipule via sa référence. Référence perdue, objet perdu. Un objet n'est pas une classe.