Faculté des Sciences Économiques et de Gestion de Sfax Département d'Informatique Support de Cours Programmation Orientée Objet Auditoire 2ème Licence Fondamentale en Informatique de Gestion Responsable Nahla Zaaboub Haddar Année Universitaire : 2019-2020 Cours de Programmation Orientée Objet 0 Plan du Cours Chapitre Chapitre Chapitre Chapitre Chapitre 1 : Introduction générale 2 : Classes et Objets en JAVA 3 : Paquetages 4 : Héritage et Polymorphisme 5 : Exceptions Cours de Programmation Orientée Objet 1 Chapitre 1 : Introduction Enjeux de la programmation Un produit logiciel doit remplir les critères suivants : Exactitude (fonctionnement correspondant aux spécifications) Robustesse (vis-à-vis des conditions anormales) Evolutivité (facilité à ajouter de nouvelles fonctionnalités) Généricité, Réutilisabilité (possibilité de réutiliser des modules dans d’autres logiciels) Portabilité (aptitude à fonctionner sur différentes plateformes) Performances (temps d’exécution, ressources consommées) Cours de Programmation Orientée Objet 3 1.1 Programmation procédurale Principe : Programmation centrée sur les procédures (opérations) Décomposition des fonctionnalités d'un programme en procédures (ou fonctions) qui vont s'exécuter séquentiellement Couplage procédures/données Les données sont indépendantes des procédures Les données à traiter sont passées en arguments aux procédures Limites : Programme centré traitements : Changement de spécification et ajout de nouvelles fonctionnalités plus fréquent, les traitements étant généralement beaucoup moins stables que les données Modularité et abstraction absente (ou presque) Peu devenir complexe très rapidement La maintenance et l'ajout de nouvelles fonctionnalités difficiles. Elles demandent de modifier ou d'insérer des séquences dans ce qui existe déjà. Réutilisation ardue => "Couper-coller" = DANGER! Travail d'équipe difficile (peu modulaire), donc la qualité du code en souffre Cours de Programmation Orientée Objet 5 1.2 Programmation OO Historique : Les années 70 : SmallTalk , apparition des concepts de base : objet, encapsulation, polymorphisme, héritage , etc. Les années 80 : La montée en puissance de l’orienté objet Apparition de nouveaux langages : Objective C ,C++, Eiffel, … Les années 90 : l’âge d'or de l'extension de la POO : Standardisation de C++ Apparition du langage de programmation Java Depuis, évolution de l’orientée objet: Analyse par objet (AOO). La conception orientée objet COO Les bases de données orientées objets (SGBDOO) Cours de Programmation Orientée Objet 6 Principe : Elle est centrée sur les données : les éléments du champ de l’étude (réels ou conceptuels) sont représentés par des entités appelées "objets" en adoptant un haut niveau d'abstraction. Elle se base principalement sur les concepts de : objet, classe, encapsulation et héritage. Programme OO Cours de Programmation Orientée Objet 7 1.3 Apports de la POO 1.3.1 Objet Le concept d’objet est utilisé pour modéliser informatiquement des "objets" concrets de la vie courante (voiture, personne, etc.) ou des objets conceptuels (abstraits) (date, rdv, etc.). Objet = identité + état + comportement L'identité : adresse en mémoire L’état d’un objet : valeur de ses attributs Le comportement d’un objet : ses méthodes. Cours de Programmation Orientée Objet 8 1.3.2 Classe Une classe est la description d’une famille d’objets ayant une même structure et un même comportement. Elle est caractérisée par : Un nom Une composante statique : des champs (ou attributs) nommés ayant un nom et un type. Ils caractérisent l’état des objets pendant l’exécution du programme Une composante dynamique : des méthodes représentant le comportement des objets de cette classe. Elles manipulent les champs des objets et caractérisent les actions pouvant être effectuées par les objets. La classe est un moule et l’objet est ce qui est moulé à partir de cette classe Les objets sont appelés des instances du modèle défini au travers de la classe Une classe permet d’instancier plusieurs objets Chaque objet est instance d’une seule classe 9 Cours de Programmation Orientée Objet 10 1.3.3 Encapsulation L'encapsulation consiste à rassembler les données et les traitements afférents au sein d'une structure unique (entité) Elle impose de manipuler les données via les méthodes Elle permet de faire abstraction du fonctionnement interne (c'està-dire, la mise en œuvre) d'une classe et ainsi de ne se préoccuper que des services rendus par celle-ci. Elle facilite l’évolution et la réutilisation Cours de Programmation Orientée Objet 11 1.3.4 Héritage L’héritage permet de définir une nouvelle classe à partir d’une classe existante. La nouvelle classe comporte les mêmes propriétés de la classe de base, auxquelles s’ajoutent des propriétés (méthodes et/ou attributs) spécifiques à cette nouvelle classe. L’héritage facilite largement la réutilisation et l’extension des applications. Cours de Programmation Orientée Objet 12 1.4. Le Langage Java Java est un langage de programmation orienté objet, créé en 1995 par James Gosling, Patrick Naughton et Mike Sheridan qui étaient employés de Sun Microsystems. Cours de Programmation Orientée Objet 13 Sa syntaxe est très proche du C. Ses caractéristiques ainsi que la richesse de son écosystème et de sa communauté lui ont permis d’être très largement utilisé pour le développement d’applications de grande envergure. Java est largement utilisé pour d’applications d’entreprises et mobiles. Cours de Programmation Orientée Objet le développement 14 1.4.1 Caractéristiques de JAVA Java est orienté objet : Chaque fichier source contient la définition d’une ou plusieurs classes qui sont utilisées les unes avec les autres pour former une application Simplicité : Pas de pointeurs, pas d’héritage multiple Java est fortement typé : Toutes les variables sont typées et il n’existe pas de conversion automatique qui risquerait une perte de données. Gestion de la mémoire: L’allocation de la mémoire pour un objet est automatique à sa création et Java récupère automatiquement la mémoire inutilisée. Cours de Programmation Orientée Objet 15 Java est économe: Le byte code a une taille relativement petite car les bibliothèques de classes requises ne sont liées qu’à l’exécution. Java est multitâches: Java permet l’utilisation des threads qui sont des unités d’exécution isolées. La JVM, elle-même, utilise plusieurs threads. Java est interprété et portable (1) Code Source (2) Byte-code (1) : Compilation (2) : Interprétation Cours de Programmation Orientée Objet JVM Sun JVM Mac JVM PC 16 1.4.2 Les différentes éditions et versions de Java Le JRE (Java Runtime Environment) contient uniquement l’environnement d’exécution des programmes. Le JRE seul doit être installé sur les machines où des applications Java doivent être exécutées. JDK: ensemble d’outils et d’API pour permettre le développement de programmes avec Java. Il contient luimême le JRE. J2SDK : Depuis sa version 1.2, Java a été renommé Java 2. Les numéros de version 1.2 et 2 désignent donc la même version. Le JDK a été renommé J2SDK (Java 2 Software Developement Kit) mais la dénomination JDK reste encore largement utilisée. Cours de Programmation Orientée Objet 17 Java Standard Edition (J2SE / Java SE): Environnement de développement d’exécution contenant un ensemble complet d’API pour des applications de types desktop. Elle sert de base en tout ou partie aux autres plateformes. Java Enterprise Edition (J2EE / Java EE): environnement reposant intégralement sur Java SE pour le développement d’applications d’entreprises. Java Micro Edition (J2ME / Java ME): environnement pour le développent d’applications sur appareils mobiles et embarqués dont les capacités ne permettent pas la mise en œuvre de Java SE. Cours de Programmation Orientée Objet 18 1.4.3 Compilation et exécution d’un programme java Le point d'entrée pour l'exécution d'une application Java est la méthode main() de la classe spécifiée à la machine virtuelle public static void main(String [ ] args) Cours de Programmation Orientée Objet 19 Variables importantes pour démarrer un programme java : CLASSPATH : chargement dynamique des classes JAVA_HOME : répertoire racine de la JDK Cours de Programmation Orientée Objet 20 Chapitre 2 : Classes et Objets 2.1 La syntaxe d’une classe [public] class NomClasse { [private/public] typeAttribut1 nomAttribut1 [= valeur1]; … [private/public] typeAttributN nomAttributN [= valeurN]; [private/public] typeRetour nomMéthode1 ([type param11,…, type param1M] ){…} … [private/public] typeRetour nomMéthodeN ([type paramN1,…, type paramNM] ){…} } Cours de Programmation Orientée Objet 22 Pour une classe, le modificateur d’accès public donne la possibilité d'utiliser cette classe à toutes les autres classes de l’application. Les modificateurs d'accès à l'attribut ou à la méthode private et public: private indique que l'accès est réservé aux méthodes de la même classe public donne la possibilité d'accès à toutes les méthodes des autres classes Une fois créée, la classe devient un vrai type java. Ce type peut être utilisé : pour la déclaration de variables locales pour déclaration d'attributs d'un objet comme type de paramètre de méthode comme type de retour d'une méthode Cours de Programmation Orientée Objet 23 Le type d’un attribut peut être un type primitif, un tableau ou le nom d’une classe. Types primitifs char: Caractère Unicode (2 octets) byte: Entier très court (1 octet) short: Entier court (2 octets) int: Entier (4 octets) long: Entier long (8 octets) float: Nombre réel simple (4 octets) double: Nombre réel double (8 octets) boolean: Valeur logique (true/false, 1 octet) Exemple 1 class Rectangle { private int longueur ; private int largeur ; public int surface ( ) { return (longueur*largeur) ; } public void initialise (int x, int y) { longueur =x ; largeur = y ;} public static void main (String [] args) { Rectangle rec=new Rectangle(); rec.initialize(3,4); int s = rec.surface(); System.out.print(s); } }//fin classe Rectangle Exemple 2: public class Etudiant { private int matricule; private String nom; private String prenom; private String filiere; private int niveau; private int groupe; public void changerFiliere(String f) {filiere = f;} public void changerNiveau (int n) {niveau = n;} public void changerGroupe (int g) {groupe = g;} } //Fin classe Etudiant Cours de Programmation Orientée Objet 26 2.2 La notion de Constructeur Le constructeur d'une classe est une méthode appelée une seule fois par objet et ce au moment de sa création. Le constructeur porte le même nom que la classe Le rôle du constructeur est d'initialiser les attributs de l'objet En l’absence d’un constructeur défini par le programmeur, JAVA offre un constructeur non paramétré qui initialise les attributs de l'objet crée par les nulls correspondant à leurs types (0 pour int, null pour les références aux objets, …) Le programmeur peut définir ses propres constructeurs pour initialiser certains attributs Le constructeur est toujours publique et ne possède pas de type de retour (même pas void). Cours de Programmation Orientée Objet 27 Si tous les constructeurs d’une classe doivent affecter la même valeur à un attribut, alors il est préférable d’affecter cette valeur directement à cet attribut dans la définition de la classe. Un attribut peut être déclaré avec le mot clé final, afin d’imposer qu’il ne soit initialisé qu’une seule fois. Un attribut déclaré final doit être initialisé au plus tard dans le constructeur. Toute tentative de modification d’un attribut final conduira à une erreur de compilation. Cours de Programmation Orientée Objet 28 2.3 La déclaration et la création d'objets La déclaration des objets de type classe est : nomClasse nomObjet; La déclaration ne crée pas un objet, mais uniquement une référence nulle du type mentionné. Pour créer un objet, on utilise l'opérateur new suivi de l’appel à un constructeur de la classe de l’objet : new nomClasse(expr1, expr2, ... ) l'opérateur new se charge de : Allouer l'espace mémoire nécessaire pour stocker les attributs de l'objet en cours de construction Appeler le constructeur de l'objet adéquat pour initialiser les attributs. Le choix du constructeur se fait en fonction des paramètres passés Retourner une référence sur l'objet créé Cours de Programmation Orientée Objet 29 Il est possible d'avoir à un instant t plusieurs références pour désigner un même objet. Les opérateurs possibles sur les références d'objets sont : = pour l’affectation == et != pour la comparaison de références instanceof pour la vérification du type d’un objet Un objet qui n'est référencé par aucune référence est détruit par le ramasse miettes (Garbage Collector) qui s'exécute en permanence. Avant qu’un objet soit soumis au ramasse-miettes, Java appelle la méthode finalize() de sa classe. Cours de Programmation Orientée Objet 30 2.4. La manipulation d’objets Accès aux attributs: les attributs d’objet sont désignés selon la syntaxe suivante: nomObjet.nomAttribut Invocation de méthodes: les méthodes sont invoquées selon la syntaxe suivante: nomObjet.nomMethode() Remarque: Au sein de la classe propriétaire, on peut désigner un attribut ou une méthode uniquement par son nom. On ne peut accéder à un attribut de l’extérieur de la classe là où il a été défini que si on est autorisé à le faire On ne peut invoquer une méthode de l’extérieur de la classe là où elle a été définie que si on est autorisé à le faire Cours de Programmation Orientée Objet 31 2.5. Les accesseurs Ce sont les méthodes d’accès aux attributs d’une classes. On distingue : Les accesseurs en lecture (getters) de la forme getNomAttribut( ). Ils fournissent des informations relatives à l'état d'un objet, c. à d. des valeurs de certains attributs sans les modifier les accesseurs en écriture (setters) de la forme setNomAttribut( ). Ils modifient l'état d'un objet, c. à d. les valeurs de certains attributs Cours de Programmation Orientée Objet 32 2.6. Les attributs statiques Un attribut statique (ou attribut de classe) est un attribut déclaré avec le mot réservé static. L’existence de cet attribut ne dépend pas des instances de la classe. S’il y a eu une instanciation, une seule copie de cet attribut est partagée par toutes les instances. Les attributs statiques sont désignés selon la syntaxe suivante: nomClasse.nomAttribut Cours de Programmation Orientée Objet 33 2.7. Les méthodes statiques Une méthode statique (ou méthode de classe) est une méthode déclarée avec le mot réservé static. L’exécution d’une telle méthode ne dépend pas des objets de la classe. Les méthodes statiques sont désignées selon la syntaxe suivante : nomClasse.nomMéthode(). Remarque : Un attribut d’objet (non static) ne peut pas être manipulé directement par une méthode de classe (static). Cours de Programmation Orientée Objet 34 2.8. Surcharge des méthodes Dans une même classe, une méthode (y compris le constructeur) peut être définie plusieurs fois avec le même nom à condition de se différencier par le nombre et/ou le type des paramètres transmis. C’est le compilateur qui décidera de la bonne méthode à utiliser en fonction des paramètres d'appel. Cours de Programmation Orientée Objet 35 2.9. La référence sur l'objet courant this Le mot-clé this représente une référence sur l'objet courant, c.à.d., celui qui possède la méthode qui est en train de s'exécuter La référence this peut être utile : variable locale (ou un paramètre) "cache", en portant le même nom, un attribut de la classe. Lorsqu'une Lorsqu’on ne connaît pas encore une référence pour l’objet en cours. Cours de Programmation Orientée Objet 36 2.10. La méthode toString() Généralement, on décrit dans chaque classe une méthode ayant le prototype suivant : public String toString() L’objectif de cette méthode est de retourner une description (totale ou partielle) sous forme d’une chaîne de caractères d’un objet L’utilité de toString() s’accroît lorsque les attributs ne sont pas publics En réalité, la description d’une méthode toString() correspond à une redéfinition d’une autre version de cette méthode qui se trouve par défaut dans chaque classe Cours de Programmation Orientée Objet 37 2.11. La classe String Les chaînes de caractères sont des objets de la classe String Elles sont constantes, leurs valeurs ne peuvent être changées après leur création. Construction String str = "abc"; est équivalent à String str = new String("abc"); L’opérateur (+) est surchargé pour concaténation des chaînes de caractères Cours de Programmation Orientée Objet permettre la 38 Un objet concaténé à une chaîne de caractères est converti implicitement en chaîne. Toute conversion se fait de manière automatique en faisant appel à la méthode toString(). Méthodes de la classe String : Longeur d’une chaîne de caractères : int length() : Renvoie la longueur de la chaîne de caractères Comparaison de chaînes de caractères int compareTo(String anotherString) : Compare une chaîne de caractère à une autre. Renvoie une valeur <0 ==0 ou > 0. La comparaison est une comparaison lexicographique. Cours de Programmation Orientée Objet 39 boolean equals(Object anObject) : Compare la chaîne a un objet et retourne true en cas d’égalité et false sinon boolean equalsIgnoreCase(Object anObject) : Compare la chaîne a un objet et retourne true en cas d’égalité et false sinon ( on ignore la casse) Conversions String toLowerCase() : Retourne une chaîne égale à la chaîne convertie en minuscules. String toUpperCase() : Retourne une chaîne égale à la chaîne convertie en majuscules. Cours de Programmation Orientée Objet 40 Caractère et sous-chaîne char charAt(int i) : Retourne le caractère à l’indice i spécifié en paramètre. Ex. : char c= "programme".charAt(3);// c=‘g’ String substring(int d) : Sous-chaîne depuis d jusqu’à la fin Ex. : String s= "programme".substring(3);//s= "gramme" String substring(int d, int f) Sous-chaîne depuis d jusqu’au caractère d’indice f non inclus. Ex. : String s= "programme".substring(3, 6);//s= "gra" boolean startsWith(String prefix) : Renvoie true si prefix est un préfixe de la chaîne Ex. : boolean b= "programme".startsWith("pro");//b= true Cours de Programmation Orientée Objet 41 boolean endsWith(String suffix) : Retourne true si suffix est un suffixe de la chaîne Ex. : boolean b= "programme".endsWith("pro");//b=false Recherche int indexOf(String str) : Retourne l’indice de la première occurrence de la chaîne str int lastIndexOf(String str): Retourne l’indice de la dernière occurrence de la chaîne str Cours de Programmation Orientée Objet 42 2.12 Passage d’arguments à une méthode Le passage d’arguments à une méthode en JAVA est toujours un passage par valeur Cours de Programmation Orientée Objet 43 2.13. Les tableaux Un tableau est considéré comme un objet Les tableaux sont toujours manipulés par référence La déclaration d'un tableau ne fait qu'associer son identificateur à une variable de nature référence initialisée à null La taille d'un tableau est indiquée lors de sa création par l’opérateur new Cours de Programmation Orientée Objet Avancée 44 Un tableau peut être construit sur la base d'un type primitif ou d'un type construit (classe ou tableau) Les éléments d'un tableau sont initialisés par des valeurs nulles On peut connaître la taille d'un tableau par l'attribut length Un tableau qui n'est plus référencé est éliminé par le ramasse miettes Java permet de gérer des tableaux à plusieurs dimensions. Un tableau à plusieurs dimensions est géré comme un tableau de tableaux (de tableaux …) Cours de Programmation Orientée Objet 45 Chapitre 3 : Les paquetages 3.1. Notion de package Un package (paquetage) est un regroupement de classes participant au même centre d'intérêt. Les objectifs sont : fournir une organisation cohérente des classes. faciliter le développement de bibliothèques. définir un certain niveau de protection pour les classes Représentation graphique : produits produits +FamillesProduits +Produits +Angrais +ProduitIndustriel Cours de Programmation Orientée Objet Avancée 47 3.2. Exemples de packages : Core API de java Java propose une définition très claire du mécanisme d’empaquetage qui permet de gérer les APIs (Interfaces de Programmation des Applications) Core API de java regroupe un ensemble de classes prédéfinies d'usage général que l'on retrouve dans le JDK ou le JRE sur toutes les plateformes java. Core API est découpée en plusieurs packages : java.applet : Gestion des applets java.awt : Gestion du fenêtrage et de son contenu java.io : Gestion des entrées-sorties et des fichiers java.lang : Gestion des types et des éléments de base du langage java.util : Structures de données et utilitaires Cours de Programmation Orientée Objet Avancée 48 3.3. Packages et système de fichiers A chaque package correspond physiquement un répertoire formé des fichiers des classes du package. Un package peut contenir : des classes un autre package (un sous-package) Ainsi, à une structure arborescente de packages correspond une structure arborescente de répertoires dont les noms coïncident avec les noms des composants de la structure de packages. 49 Cours de Programmation Orientée Objet Avancée 49 3.4. Package : espace de nommage Les package introduisent la notion d'espace de noms Les espaces de noms servent à désambiguïser les conflits entre plusieurs classes portant le même nom. Toute classe doit toujours appartenir a un (et un seul) espace de nom (i.e., à un package) Lorsque l'on n'a pas défini de package, java définit implicitement un package associé au répertoire de travail; c'est le package par défaut. Cours de Programmation Orientée Objet Avancée 50 3.5. Création de packages La définition d’un paquetage se fait au niveau du fichier source ; on place, en début de fichier, une instruction de la forme : package nomPackage; Exemples : package achat package achat.reglement Toutes les classes d’un même fichier source appartiennent donc toujours à un même paquetage Les classes de tous les fichiers commençant par le même nom de paquetage appartiennent à ce paquetage Cours de Programmation Orientée Objet Avancée 51 3.6. Utilisation des classes d’un package Il y a deux manières d'utiliser une classe d’un package : En utilisant le nom du package suivi du nom de la classe Exemple : java.util.Date v = new java.util.Date(); En utilisant le mot clé import pour importer (inclure) le package auquel appartient la classe. Exemple : import java.util.Date; import java.util.*; ou bien Si l’on veut utiliser deux classes portant le même nom et définies dans deux packages différents, on doit obligatoirement utiliser la première méthode. Cours de Programmation Orientée Objet Avancée 52 Cours de Programmation Orientée Objet 53 Remarques : En citant tout un paquetage dont certaines classes sont inutilisées, vous ne vous pénaliserez ni en temps de compilation, ni en taille du byte codes. L’instruction : import package1.* ; ne concerne que les classes du paquetage package1. Si, par exemple, vous avez créé un sous-paquetage nommé package1.package11, ses classes ne seront nullement concernées. Le package java.lang est automatiquement importé par le compilateur. Ceci vous permet d’utiliser des classes standard telles que Math, System, String ou Integer, sans import. C'est dans le CLASSPATH que la jvm cherche les classes mentionnées après les directives import Cours de Programmation Orientée Objet Avancée 54 3.7. Packages et droits d’accès Une classe public est accessible à toutes les autres classes (moyennant éventuellement le recours à une instruction import) appartenant éventuellement à des packages différents Sans le mot-clé public, la classe n’est accessible qu’aux classes du même paquetage. Ne confondez pas le droit d’accès à une classe avec le droit d’accès à un membre d’une classe. Ainsi, private a un sens pour un membre, il n’en a pas pour une classe. Cours de Programmation Orientée Objet Avancée 55 Chapitre 4 : Héritage et Polymorphisme Cours de Programmation Orientée Objet Avancée 56 4.1. Le concept de l’héritage L'héritage est une propriété essentielle de la programmation orientée objet. Ce mécanisme permet d'ajouter des fonctionnalités à une classe (une spécialisation) en créant une sous-classe qui hérite des propriétés de la classe parente et à laquelle on peut ajouter des propriétés nouvelles. La classe qui hérite est appelée sous-classe (ou classe dérivée) de la classe parente (qui est également appelée super-classe). Tout objet de la classe dérivée est un objet de la classe de base. L’inverse n’est pas forcément vrai. Cours de Programmation Orientée Objet Avancée 57 En Java, une classe ne peut hériter que d'une seule classe parente. On parle dans ce cas d'héritage simple (par opposition à l'héritage multiple qui permet à une classe d'hériter de plusieurs classes parentes). Représentation graphique : Cours de Programmation Orientée Objet Avancée 58 4.2. La syntaxe de déclaration d’une sousclasse La déclaration d'une sous-classe s'effectue en utilisant le motclé extends suivi du nom de la classe parente. [modificateur d'accès] class ClasseDérivée extends ClasseBase { ….} Exemple : public class PointColore extends Point { private String couleur; public void colorer(String c) {couleur = c; }} Remarque : java permet d'interdire l'héritage d'une classe en la déclarant avec le modificateur final Cours de Programmation Orientée Objet Avancée 59 4.3. Le transtypage La relation d'héritage ("Est un...") permet de traiter les objets des sous-classes comme s'ils étaient des objets de leur classe parente (par généralisation). Si nécessaire, le système effectue une conversion automatique de la sous-classe vers la classe parente (Upcasting). Une conversion explicite (transtypage, casting) d'un objet de la classe parente vers un objet de la sous-classe (Downcasting) est possible si l'instance à convertir référence effectivement (au moment de l'exécution) un objet de la sousclasse considérée (sinon, il y aura une erreur ClassCastException à l'exécution). Cours de Programmation Orientée Objet Avancée 60 L'opérateur instanceof permet de tester (à l'exécution) l'appartenance d'un objet à une classe (ou une interface) donnée. L'upcasting et le downcasting n'engendrent aucune opération ni changement en mémoire (c'est une autre "vue" de l'objet) Cours de Programmation Orientée Objet Avancée 61 4.4. Le constructeur d’une sous-classe Un constructeur d'une sous-classe peut faire appel à un constructeur de la classe parente en utilisant le mot réservé super selon la syntaxe suivante : super(Expr1, Expr2, ...); Si un constructeur d'une sous-classe invoque explicitement un constructeur de la classe parente, l'instruction super(...) doit être la première instruction du constructeur. Si l'on ne fait pas explicitement appel à un constructeur de la classe parente, une invocation du constructeur par défaut de la super-classe (constructeur sans paramètre) sera automatiquement ajoutée (comme première instruction). Si un tel constructeur n'existe pas dans la classe parente, une erreur sera générée à la compilation. Cours de Programmation Orientée Objet Avancée 62 Le langage garantit ainsi que tous les éléments des classes parentes aient été élaborés avant la création d'un objet de la classe considérée. on peut, dans le corps de la sous-classe accéder au champ de la classe parente en utilisant le mot-clé super suivi d'un point et du nom du champ. Cours de Programmation Orientée Objet Avancée 63 4.5. Héritage et droits d’accès Le modificateur protected appliqué aux membres (champs ou méthodes) d'une classe indique que ces champs ne sont accessibles que dans la classe de définition, dans les classes du même paquetage et dans les sous-classes de cette classe (indépendamment du paquetage). Il s'agit d'un accès plus restrictif que public mais moins restrictif que l'accès par défaut (package). Si les membres (attributs et méthodes) hérités sont déclarés avec le modificateur private dans la classe de base, la classe dérivée n'a pas le droit de les manipuler directement Un membre hérité est (si l'accès est autorisé) désigné par super.membre Cours de Programmation Orientée Objet Avancée 64 4.6. La classe Object La classe Object (déclarée dans le paquetage java.lang) est l'ancêtre de toutes les classes Java (c'est la racine unique de l'arbre des classes) :Tous les objets sont des Object ! Si l'on ne définit pas explicitement une classe parente (avec extends), la super-classe par défaut est Object. La classe Object est la seule classe Java qui ne possède pas de classe parente. Toutes les classes héritent donc des méthodes de la classe Object (par exemple toString(), equals(), etc). Cours de Programmation Orientée Objet Avancée 65 4.7. La redéfinition de méthodes Lorsqu'une classe définit une méthode d'instance en utilisant la même signature (même nom, type de retour [év. une sousclasse], paramètres, etc.) qu'une méthode de sa classe parente, cette méthode redéfinit la méthode de sa superclasse. C'est toujours la méthode associée au type effectif de l'objet référencé qui est exécutée, même si l'objet est référencé par une variable déclarée avec le type d'une classe parente. Si une méthode est redéfinie dans une sous-classe, le type de retour doit être identique à celui de la méthode correspondante de la classe parente. Cours de Programmation Orientée Objet Avancée 66 En redéfinissant une méthode, il est possible d'étendre sa zone de visibilité (private package protected public) mais non de la restreindre. Attention à bien distinguer (et ne pas confondre) les notions de surcharge (overloading) et de redéfinition (overriding) de méthodes. JAVA permet d'interdire la redéfinition d'une méthode (si elle est héritée) en la déclarant avec le modificateur final Une méthode static et/ou private ne peut pas être redéfinie. Cours de Programmation Orientée Objet Avancée 67 4.8. Polymorphisme En Java, dans la plupart des situations où il y a des relations d'héritage, la détermination de la méthode à invoquer n'est pas effectuée lors de la compilation. C'est seulement à l'exécution que la machine virtuelle java déterminera la méthode à invoquer selon le type effectif de l'objet référencé à ce moment là. Ce mécanisme s'appelle "Recherche dynamique méthode" (Late Binding ou Dynamic Binding). de Ce mécanisme de recherche dynamique (durant l'exécution de l'application) sert de base à la mise en œuvre de la propriété appelée polymorphisme. Cours de Programmation Orientée Objet Avancée 68 On pourrait définir le polymorphisme comme la propriété permettant à un programme de réagir de manière différenciée à l'envoi d'un même message (invocation de méthode) en fonction du type effectif des objets qui reçoivent ce message. Il s'agit donc d'une aptitude d'adaptation dynamique du comportement selon les objets en présence. Avec l'encapsulation et l'héritage, le polymorphisme est une des propriétés essentielles de la programmation orientée objet. Cours de Programmation Orientée Objet Avancée 69 4.9. Classes et méthodes abstraites Une méthode abstraite est une méthode qui ne contient pas de corps. Elle possède simplement une signature de définition suivie du caractère point-virgule (pas de bloc d'instructions). Une classe abstraite est une classe qui ne peut pas être instanciée. Elle peut contenir des méthodes abstraites et des méthodes habituelles (appelée parfois méthodes concrètes). Une méthode abstraite doit obligatoirement être déclarée avec le modificateur abstract. Exemple : public abstract double surface(); Cours de Programmation Orientée Objet Avancée 70 Une classe possédant une ou plusieurs méthodes abstraites devient obligatoirement une classe abstraite. Cette classe doit également être déclarée avec le modificateur abstract. Comme les autres classes, une classe abstraite définit un nouveau type qui peut être associé à un identificateur (déclaration de variables, champs, tableaux, paramètres formels, …). Cours de Programmation Orientée Objet Avancée 71 Une classe abstraite ne peut pas être instanciée : on ne peut pas créer d'objet en utilisant l'opérateur new. Une sous-classe d'une classe abstraite ne peut être instanciée que si elle redéfinit chaque méthode abstraite de sa classe parente et qu'elle fournit une implémentation (un corps) pour chacune des méthodes abstraites. Une telle sous-classe est souvent appelée sous-classe concrète. Si une sous-classe d'une classe abstraite n'implémente pas toutes les méthodes abstraites dont elle hérite, cette sousclasse est elle-même abstraite (et ne peut donc pas être instanciée). Cours de Programmation Orientée Objet Avancée 72 Les méthodes déclarées avec l'un des modificateurs static, private ou final ne peuvent pas être abstraites étant donné qu'elles ne peuvent pas être redéfinies dans une sousclasse. Une classe déclarée final ne peut pas contenir de méthodes abstraites car elle ne peut pas être sous-classée. Une classe peut être déclarée abstract même si elle ne possède pas réellement de méthode abstraite. Cours de Programmation Orientée Objet Avancée 73 4.10. Les interfaces Une interface représente une pure spécification qui définit les méthodes disponibles d'une famille d'objets, mais ne définit aucune implémentation (c'est une promesse de comportement). Du point de vue syntaxique, la définition d'une interface ressemble beaucoup à la définition d'une classe abstraite. public interface MonInterface { public void meth();} Une déclaration référence. d'interface définit un nouveau type Cours de Programmation Orientée Objet Avancée 74 Le corps d'une interface ressemble beaucoup à celui d'une classe abstraite avec cependant les différences suivantes : Une interface ne peut définir que des méthodes abstraites. Le modificateur abstract n'est pas nécessaire. Toutes les méthodes abstraites sont implicitement publiques même si le modificateur public est omis. Une interface ne peut pas contenir de méthodes statiques. Une interface ne peut pas définir de champs d'instance (attribut). Une interface peut cependant contenir des constantes déclarées static et final (tous les champs sont implicitement static et final même si les modificateurs correspondants sont omis). Une interface ne définit pas de constructeur (on ne peut pas l'instancier et elle n'intervient pas dans le chaînage des constructeurs). Cours de Programmation Orientée Objet Avancée 75 En Java, une classe ne peut hériter que d'une et d'une seule classe parente (héritage simple). Par contre, elle peut implémenter une ou plusieurs interfaces en utilisant la syntaxe suivante : class NomClasse implements interface1[, interface2] L'implémentation d'une ou de plusieurs interfaces (implements) peut être combinée avec l'héritage simple (extends). La clause implements doit suivre la clause extends. Exemple : public class Cercle extends Forme implements Imprimable {...} Cours de Programmation Orientée Objet Avancée 76 Les interfaces peuvent avoir des sous-interfaces (tout comme les classes peuvent avoir des sous-classes). Comme pour les classes, le mot-clé extends est utilisé pour créer une sousinterface. public interface MonInterface extends TonInterface {...} Une sous-interface hérite de toutes les méthodes abstraites et de toutes les constantes de son interface parente et peut définir de nouvelles méthodes abstraites ainsi que de nouvelles constantes. Contrairement aux classes, une interface peut posséder plusieurs interfaces parentes (héritage multiple). public interface MonInterface extends TonInterface, SonInterface {...} Cours de Programmation Orientée Objet Avancée 77 Une classe qui implémente une sous-interface doit implémenter les méthodes abstraites définies directement par l'interface ainsi que les méthodes abstraites héritées de toutes les interfaces parentes de la sous-interface. Des conflits de noms (collision) peuvent se produire lorsqu'une classe implémente plusieurs interfaces comportant des noms de méthodes ou de constantes identiques. Il faut distinguer plusieurs situations : Plusieurs méthodes portent des signatures identiques : Pas de problème, la classe doit implémenter cette méthode Mêmes noms de méthodes mais profils de paramètres différents : Implémentation de deux ou plusieurs méthodes surchargées Cours de Programmation Orientée Objet Avancée 78 Mêmes noms de méthodes, profils de paramètres identiques, mais types des valeurs de retour différents : Pas possible d'implémenter les deux interfaces (cela provoquera une erreur à la compilation : Interface-Collision) Noms de constantes identiques dans plusieurs interfaces : Doivent être accédées (Interface.Constante) en utilisant la notation qualifiée Cours de Programmation Orientée Objet Avancée 79 4.11. Classes anonymes Une classe anonyme n’a pas de nom Elle sert à écrire une sous-classe "à usage unique" , c. à d. qui n’est instanciée qu’à un seul endroit du programme. L’unique instruction d’une classe anonyme : crée une instance de la classe ; déclare sa super-classe ou l’interface qu’elle implémente ; redéfinit avec l’implémentation voulue les méthodes de sa superclasse ou de l’interface implémentée Cours de Programmation Orientée Objet 80 Exemple : interface Affichable { public void affiche() ;} public class MaClasse { public static void main (String[] args) { Affichable a = new Affichable() { @Override public void affiche () { System.out.println ("Je suis un anonyme implementant Affichable") ;} } ;//fin classe anonyme a.affiche() ;}//fin main }//fin classe MaClasse Cours de Programmation Orientée Objet 81 Une classe anonyme ne peut pas introduire de nouvelles méthodes La référence de la classe anonyme peut être conservée dans une variable (d’un type de base ou d’un type interface). transmise en argument d’une méthode ou en valeur de retour. Cours de Programmation Orientée Objet 82 Exemple : interface MonInterface { ..... } public class Util { public static void foo( MonInterface m) { ..... } //fin methode public static void main(String[ ] args) { foo(new MonInterface() { // implémentation des méthodes de MonInterface }) ; } //fin main }//fin classe Util Cours de Programmation Orientée Objet 83 Chapitre 5 : Les exceptions Cours de Programmation Orientée Objet 84 5.1. Pourquoi les exceptions Avec une programmation classique, de grandes portions de code sont réservées à la détection et à la gestion des cas exceptionnels (division par zéro, problème lors de l’ouverture d’un fichier, mauvaise saisie de données,…) Ces portions de code sont toujours fortement imbriquées dans le reste du code Problèmes: La lisibilité du code diminue Le code devient difficile à maintenir Certains cas exceptionnels sont oubliés ou mal traités, ce qui peut donner des résultats erronés ou provoquer des interruptions non avisées Cours de Programmation Orientée Objet 85 Solution : séparer les instructions qui traitent les exceptions du reste du code Comment ? Définir chaque type d'exception sous forme d'une classe qui hérite de java.lang.Exception Lors de la rencontre d'un cas d'exception, la méthode en question lance (crée et diffuse) un objet de la classe d'exception appropriée Une exception lancée par une méthode est soit traitée dans cette méthode soit propagée. Cours de Programmation Orientée Objet 86 5.2. Classes d’exceptions Il y a beaucoup de types d’exceptions prédéfinis en Java. Ils dérivent tous de la classe Exception. Il est aussi d’exceptions. possible d’ajouter de nouvelles classes La classe d’une exception doit être suffisamment précise pour que le programmeur puisse savoir, juste en connaissant cette classe, quel a été le problème. Exemple public class QuantiteNonValide extends Exception { } Cours de Programmation Orientée Objet 87 Hiérarchie des classes d’exceptions prédéfinies en java : Hiérarchie des exceptions prédéfinies en java Cours de Programmation Orientée Objet 88 5.3. Déclenchement d’une exception Une exception est déclenchée avec le mot clé throw qui lance un objet exception après l'avoir créé par new Chaque méthode qui lance un ou plusieurs types d'exception, doit annoncer, au niveau de son entête, la ou les classes d'exceptions qu’elle lance Exemple : public class Produit { private String code, libelle; private int quantite=0; public Produit(String code, String libelle) { this.code = code; this.libelle = libelle;} public void setQuantite(int quantite) throws QuantiteNonValide { if (quantite<0) throw new QuantiteNonValide(); else this.quantite = quantite;}} // Fin classe Produit Cours de Programmation Orientée Objet 89 5.4. Trace d’une exception La trace d'une exception est une chaîne d'appels de méthodes, de la méthode génératrice de l'exception jusqu'à la méthode main() Elle informe sur l'origine de l'exception Elle facilite de débogage du programme Elle est stockée dans l’objet Exception lancé. L’affichage de la trace se fait à l’aide de la méthode printStackTrace() de la façon suivante : e.printStackTrace(); où e est l’objet Exception lancé. Cours de Programmation Orientée Objet 90 5.5. Traitement d’une exception La gestion des objets exception déjà lancés nécessite : La surveillance des instructions susceptibles de lancer ces objets exception en les mettant dans un bloc try{ } La capture de chaque objet exception lancé dans un bloc catch { } approprié au type de l'exception Exemple : try { … p.setQuantite(qt); …} catch (QuantiteNonValide e) { e.printstacktrace();} Cours de Programmation Orientée Objet 91 Fonctionnement : Si l'exécution du code normal n'a provoqué aucune exception, l'exécution continue normalement après le dernier catch (flèches continues sur la figure) Sinon, le premier traitement d'exception qui convient, dans l'ordre du texte, est exécuté. Puis s'il n'a pas provoqué lui-même une nouvelle exception ou un arrêt du programme, ce dernier continue son exécution normale après le dernier catch (flèches en pointillés sur la figure) // instructions try { //instructions //instructions } catch (ExceptionTyp1 e) { //instructions } catch (ExceptionTyp2 e) { // instructions } // instructions Flux de contrôle avec try-catch Cours de Programmation Orientée Objet 92 Sinon, si une exception n’est pas traitée dans la méthode où elle est levée, elle se propage, en remontant la séquence des appels de méthodes, éventuellement jusqu’à la méthode main(). Si elle n’est jamais traitée, un message d'erreur s'affiche sur la console en prenant en compte les informations collectées par l'objet exception pendant sa propagation. Exemple public class Produit { …. public static void main (String args[ ]) throws QuantiteNonVlaide{ Produit p=new Produit ("12 ", "Lait1L"); p.setQuantite(-100);}} // Fin classe Produit Console : Exception in thread "main" metier.QuantiteNonValide at metier.Produit.setQuantite(Produit.java:10) at metier.Produit.main(Produit.java:16) Cours de Programmation Orientée Objet 93 Il est possible de capturer dans un seul bloc catch plusieurs exceptions, si la classe d'exception indiquée est mère de toutes les exceptions concernées Exemple : try { … } catch (Exception e) { … } //capturer tout type d'exception Les blocs catch{} doivent être présentés selon la hiérarchie des classes d'exception en question : de la classe la plus spécialisée vers la plus générale (sinon erreur de compilation) Exemple: try { … } catch (Exception e) { … catch (QuantiteNonValide e) { } … } Erreur de compilation : QuantiteNonValide derive de Exception! Cours de Programmation Orientée Objet 94 Remarques Une méthode peut propager un objet exception déclenché par l’appel d’une autre méthode dans son code. Elle doit alors déclarer la propagation de cet objet dans son entête. Elle n’a pas besoin de bloc try{} et catch() pour traiter cette exception Les méthodes qui lancent des exceptions dérivées de la classe RuntimeException peuvent ne pas mentionner ces exceptions dans leurs entêtes. Les exceptions dérivées de la classe RuntimeException peuvent ne pas être traitée avec try{} et catch(). Elles sont alors affichées sur l’écran et provoquent l’arrêt du programme. Cours de Programmation Orientée Objet 95 5.6. Bloc finally Il est possible de définir un bloc finally { } qui, contrairement au catch, n'est pas obligatoire, et qui permet de spécifier du code qui sera exécuté dans tous les cas, qu'une exception survienne ou pas. Ce code sera exécuté même si une instruction return est exécutée dans le catch ou le try ! Ce bloc permet de libérer des ressources détenues par la JVM lors du déclenchement d’une exception. Exemple : try {… // Ouvrir un fichier et lire et écrire des données } catch ( IOException e ) { System.out.println(e) ; return ;} finally { … // Fermeture du fichier } Cours de Programmation Orientée Objet 96