Cours Programmation Oriente Objet POO 2 eme anne
Cours Programmation Orientée Objet (POO) 2 eme année Licence-LMD 2019/2020 LICENCE LMD 2 eme année - Abdelkader ALEM 1
Objectif • Introduction des concepts de base de la POO. • développe des notions de base du langage JAVA • L'étudiant est censé avoir acquit pendant le module les compétences suivantes: üL'essence de la programmation objet en java üLire et comprendre des programmes en java üEcrire la solution d'un problème en java üEcrire des applications sophistiquées (utilisation de structures de données avancées) • Prés requis: Algorithmique, Structures de données, Programmation I et Programmation II LICENCE LMD 2 eme année - Abdelkader ALEM 2
Contenu de la matière • Introduction à la Programmation Orientée Objet • Les classes – Déclaration des classes – Les constructeurs et destructeurs – Les méthodes d’accès • • Encapsulation Héritage et polymorphisme Interface et implémentation Interface graphique et Applet LICENCE LMD 2 eme année - Abdelkader ALEM 3
Chapitre 1 : Introduction à la Programmation Orientée Objet LICENCE LMD 2 eme année - Abdelkader ALEM 4
De la programmation classique vers la programmation orientée objet q. La programmation classique telle que étudiée au travers des langages C, Pascal… définie un programme comme étant: Ø un ensemble de données sur lesquelles agissent des procédures et des fonctions. ØLes données constituent la partie passive du programme. Les procédures et les fonctions constituent la partie active; q Programmer dans ce cas revenait à: Ødéfinir un certain nombre de variables (structures, tableaux…) Øécrire des procédures pour les manipuler sans associer explicitement les unes aux autres. LICENCE LMD 2 eme année - Abdelkader ALEM 5
De la programmation classique vers la programmation orientée objet q. Exécuter un programme se réduit alors à appeler ces procédures dans un ordre décrit par le séquençage des instructions et en leur fournissant les données nécessaires à l’accomplissement de leurs tâches. LICENCE LMD 2 eme année - Abdelkader ALEM 6
De la programmation classique vers la programmation orientée objet q. Dans cette approche données et procédure sont traitées indépendamment les unes des autres sans tenir compte des relations étroites qui les unissent. q. Les questions qu’on peut poser dans ce cas: 1. Cette séparation (données, procédures) est elle utile? 2. Pourquoi privilégier les procédures sur les données (Que veut-on faire? )? 3. Pourquoi ne pas considérer que les programmes sont avant tout des ensembles objets informatiques caractérisé par les opérations qu’ils connaissent? q. Les langages objets sont nés pour répondre à ces questions. Ils sont fondés sur la connaissance d’une seule catégorie d’entités informatiques: le objets. q. Un objet incorpore des aspects statiques et dynamiques au sein d’une même notion. LICENCE LMD 2 eme année - Abdelkader ALEM 7
De la programmation classique vers la programmation orientée objet q Un programme est constitué d’un ensemble d’objets chacun disposant d’une partie procédures et d’une partie données. Les objets interagissent par envoie de messages. q. Un objet peut recevoir un msg qui déclenche: ØUne fonction qui modifie son état ou ØUne fonction qui envoie un msg à un autre objet LICENCE LMD 2 eme année - Abdelkader ALEM 8
De la programmation classique vers la programmation orientée objet q. Les objets sont de nouvelles sortes de variables encore plus générales que les types dérivés (ou structures). Leur caractéristique principale: ils acceptent des procédures (fonctions, subroutines) comme composantes. q La question « Que doit faire le système ? » dans l’approche classique devient « Sur quoi doit-il le faire? » et de quoi doit être composé mon programme? LICENCE LMD 2 eme année - Abdelkader ALEM 9
De la programmation classique vers la programmation orientée objet q Programmation classique Programmation Orienté e Objet LICENCE LMD 2 eme année - Abdelkader ALEM 10
La crise du logiciel q Dans les années 1970, la programmation se développe et de nouvelles technologies logicielles apparaissent : mode multi-utilisateurs, interfaces graphiques, programmation concurrente, … q. La taille des programmes augmente également : 10 000 lignes de code pour un logiciel de bonne taille dans les années 1970, 50000 dans les années 1980 (et des millions de nos jours). q. La crise du logiciel des années 70 est provoquée par : 1. l'impossibilité de maitriser la sureté des logiciels (pannes nombreuses) 2. l'inflation des délais de développement q. De bonnes techniques de développement logiciel deviennent nécessaires. LICENCE LMD 2 eme année - Abdelkader ALEM 11
Historique q La programmation objet est inventée dans les années 1970 comme une extension de la programmation procédurale. q. L'idée est de concevoir les programmes non plus comme des lignes de codes qui s'exécutent séquentiellement, mais comme des objets qui dialoguent. . q Début en Norvège à la fin des années 60 : Simula 64 est le premier langage à utiliser ce paradigme mais de façon limitée. q Smalltalk, développé à partir de 1971 par Alan Kay et publié en 1980, est le premier vrai langage objet. q. D'autres suivront : Eiffel en 1986, Python en 1991, . . . q. Des versions objets de langages existants seront développées : C++ pour le C, ADA 95 pour le ADA, Object Pascal pour le Pascal. . LICENCE LMD 2 eme année - Abdelkader ALEM 12
Historique q Année 1990: apparition de java et standardisation de C++ q. Première version de Java en 1995, développée principalement par James Gosling. q. La programmation objet devient à la fin des années 90 le paradigme dominant en programmation. LICENCE LMD 2 eme année - Abdelkader ALEM 13
Notions de base q Algorithmique Objet: Dans l’approche orienté objet un algorithme sera essentiellement vu comme un ensemble d’objets auxquels l’utilisateur envoie des messages et qui s’en envoient pendent le fonctionnement. q. Ces objets seront toujours pour l’utilisateur des boites noires et qui contiendront des variables locales, inconnues de l’environnement, et qui ne s’y intéressera d’ailleurs pas. Le seul moyen d’accéder à ces objets sera l’envoie des messages qu’ils sont capables de comprendre. LICENCE LMD 2 eme année - Abdelkader ALEM 14
Notions de base q Un objet est une entité logicielle: Ø Ayant une identité Ø Capable de sauvegarder un état c'est-à-dire un ensemble d’information dans des variables internes (attributs). Ø Répondant à des messages précis en déclenchant des activations internes appropriés qui changent l’état de l’objet (comportement). q. Ces opération sont appelées méthodes. Ce sont des fonctions liées à des objets et qui précisent le comportement de ces objets. q. Attributs : Les attributs d’un objet sont l’ensemble des informations se présentant sous forme de variable et permettant de représenter l’état de l’objet. LICENCE LMD 2 eme année - Abdelkader ALEM 15
Notions de base q Message: un message est une demande d’activation d’une méthode envoyé à un objet. q Méthodes: une méthode est une fonction ou procédure liée à un objet qui est déclenchée à la réception d’un message particulier, la méthode déclenchée correspond strictement au message reçu. q La liste des méthodes définies au sein d’un objet constitue l’interface de l’objet pour l’utilisateur. q. Signature: la signature d’une méthode représente la précision de son nom, du type de ses arguments et du type de donnée retournée. LICENCE LMD 2 eme année - Abdelkader ALEM 16
Notions de base q L’invocation d’une méthode peut déclencher 3 types d’actions: q. Manipulation des données de l’objet; q. Envoi de messages; q. Création de nouveaux objets. q. Classes: Une classe est un ensemble d’objets qui ont en commun: Ø les mêmes méthodes Øles mêmes types d’attributs q. Classe = attributs + méthodes + instanciations q Une instance d’une classe est un objet particulier d’une classe qui peut activer les méthodes de la classe et qui a des valeurs particulières de ses attributs. On définit l’objet comme l’instance d’une classe. q La classe représente pour l’objet ce que représente le type pour la variable. LICENCE LMD 2 eme année - Abdelkader ALEM 17
Notions de base q Une classe est un type abstrait qui encapsulent données et traitement. C’est une sorte de moule qui permet ensuite de créer autant d’instances qu’on veut. LICENCE LMD 2 eme année - Abdelkader ALEM 18
Notions de base q Une classe est un type abstrait qui encapsulent données et traitement. C’est une sorte de moule qui permet ensuite de créer autant d’instances qu’on veut. LICENCE LMD 2 eme année - Abdelkader ALEM 19
Notions de base public class Etudiant { private String nom; private String prenom; private int Age; public Etudiant(String nom, String prenom, int Age){ this. nom = nom; this. prenom = prenom; this. Age= Age; } public String get. Nom(){ return this. nom ; } public String getpre. Nom(){ return this. prenom ; } public int get. Age(){ return this. Age ; } LICENCE LMD 2 eme année - Abdelkader ALEM } 20
Notions de base La notion de classe Nous allons commencer par vous exposer les notions de classe, d’objet et d’encapsulation à partir d’un exemple simple de classe. - Nous verrons d’abord comment créer une classe, c’est-à-dire écrire les instructions permettant d’en définir le contenu (champs ou données) et le comportement (méthodes). - Puis nous verrons comment utiliser effectivement cette classe au sein d’un programme. LICENCE LMD 2 eme année - Abdelkader ALEM 21
Notions de base La notion de classe Nous allons commencer par vous exposer les notions de classe, d’objet et d’encapsulation à partir d’un exemple simple de classe. - Nous verrons d’abord comment créer une classe, c’est-à-dire écrire les instructions permettant d’en définir le contenu (champs ou données) et le comportement (méthodes). - Puis nous verrons comment utiliser effectivement cette classe au sein d’un programme. LICENCE LMD 2 eme année - Abdelkader ALEM 22
Chapitre 2: Les classes et les objets LICENCE LMD 2 eme année - Abdelkader ALEM 23
Introduction q. Le premier chapitre a exposé de façon théorique les concepts de base de la P. O. O. , en particulier ceux de classe et d’objet. Nous avons vu que la notion de classe généralise celle de type : qune classe comporte à la fois des champs (ou données) et des méthodes. qnotion d’objet généralise celle de variable : un type classe donné permet de créer (on dit aussi instancier) un ou plusieurs objets du type, chaque objet comportant son propre jeu de données. q En P. O. O pure, on réalise ce qu’on nomme l’encapsulation des données ; cela signifie qu’on ne peut pas accéder aux champs d’un objet autrement qu’en recourant aux méthodes prévues à cet effet. LICENCE LMD 2 eme année - Abdelkader ALEM 24
Introduction q Nous allons aborder la notion de classe dans toute sa généralité, telle qu’elle apparaît dans les concepts de P. O. O: Ø comment définir une classe et l’utiliser en instanciant des objets; Ø Nous étudierons ensuite ce que l’on nomme les champs et les méthodes de classe; Ø Les constructeurs et destructeurs ØLes méthodes d’accès ØEncapsulation LICENCE LMD 2 eme année - Abdelkader ALEM 25
La notion de Classe q Une classe Etudiant représente plusieurs choses: q. Une unité de compilation: La compilation d'un programme qui contient une classe Etudiant produir a un fichier Etudiant. class q. La définition du type Etudiant: Il peut servir à déclarer des variables comme Etudiant e; q. Un moule pour la création d'objets de type Etudiant: cela nécessite en général la définition d'un ensemble de champs (fields) décrivant l’état d'un objet de ce type et d'un ensemble de méthodes défin issant son comportement ou ses fonctionnalités q. Chaque objet de la classe Etudiant : dispose de son propre état (la valeur de ses champs) et répond au même comportement (via les méthodes de la classe) LICENCE LMD 2 eme année - Abdelkader ALEM 26
La Structure d'une classe q. Une classe est définie par son nom et son package d'appartenance (exemple: java. lang. String). ØEn l'absence de directive, les classes sont dans un package dit « par défaut » (pas de package). q Une classe peut contenir trois sortes de membres: Ø Des champs (fields) ou attributs, ØDes méthodes (methods) et constructeurs, ØDes classes internes. q Les membres statiques (static) sont dits membres de classe ØIls sont définis sur la classe et non sur les objets q. Les membres non statiques (ou d'instance) ne peuvent exister san s un objet. LICENCE LMD 2 eme année - Abdelkader ALEM 27
Les membres: champs et méthodes d'une classe q Dans une classe, il y a grossièrement ØUne zone avec des déclarations de champs: Ils définissent ce qui sera stocké dans chaque objet de cette classe. ØUne zone avec des déclarations de méthodes: Elles définissent les actions/fonctionnalités/comportements accepté par les objets de cette classe q. Chaque méthode à deux parties: ØSa signature (type de retour, nom, types des paramètres) ØSon code, qui est constitué de blocs imbriqués q. Il peut également y avoir aussi quelques blocs d’initialisation, constructeur, ou autre classe interne. LICENCE LMD 2 eme année - Abdelkader ALEM 28
Les membres: champs et méthodes d'une classe q Nous proposons de définir une classe nommée Etudiant, destinée à gérer des étudiant dans une université: public class Etudiant { // instructions de définition des champs et des méthodes de la classe } q Définition des champs: Nous supposerons ici qu’un objet de type Etudiant sera représenté par trois attributs. Ils nous suffira de les déclarer ainsi : Ø private String nom; // nom de l’étudiant Ø private int age ; // l’age de l’étudiant Ø private String adr ; // l’adresse de l’étudiant q. Ces déclarations peuvent être placées où vous voulez à l’intérieur de la définition de la classe, et pas nécessairement avant les méthodes. En général, on place les champs et méthodes privées à la fin. LICENCE LMD 2 eme année - Abdelkader ALEM 29
Les membres: champs et méthodes d'une classe q. Définition des méthodes: Supposons que nous souhaitions disposer des trois méthodes suivantes : Ø initialise pour attribuer des valeurs aux attribut d’un étudiant, Øchangeadr pour modifier l’adresse de l’étudiant. Øaffiche pour afficher un les caractéristiques d’un étudiant (nom, age et adresse) q La définition d’une méthode ressemble à celle d’une procédure ou d’une fonction dans les autres langages. Elle se compose d’un en-tête et d’un bloc. Ainsi, la définition de la méthode initialise pourra se présenter comme ceci : public void initialise (String n, int a, String ad) { nom =n ; age= a; adr=ad; LICENCE LMD 2 eme année - Abdelkader ALEM } 30
Les membres: champs et méthodes d'une classe q. L’en-tête précise : • le nom de la méthode, ici initialise ; • le mode d’accès : nous avons choisi public pour que cette méthode soit effectivement utilisable depuis un programme quelconque ; • les arguments qui seront fournis à la méthode lors de son appel, que nous avons choisi de nommer n, a et ad. • le type de la valeur de retour ; nous verrons plus tard qu’une méthode peut fournir un résultat, c’est-à-dire se comporter comme ce que l’on nomme une fonction dans la plupart des langages (et aussi en mathématiques) ; ici, notre méthode ne fournit aucun résultat, ce que l’on doit préciser en utilisant le mot-clé void. 2014/2015 31 LICENCE LMD 2 eme année - Abdelkader ALEM
Les membres: champs et méthodes d'une classe q. Les définitions des autres méthodes de la classe Etudiant ne présentent pas de difficulté particulière. Voici la définition complète de notre classe Etudiant: class Etudiant { public initialise (String n, String a, Int g) { nom = c ; adresse = a ; age= g ; } public void affiche () { System. out. println ("Etudiant de nom " + nom + " habite à " + adresse + " son age est " + age ) ; } public void Change. Adresse (String adr) { adresse = adr ; } private String nom ; // nom de l’étudiant private String adresse ; // adresse de l’étudiant private int age ; // age de l’étudiant 32 LICENCE LMD 2 eme année - Abdelkader ALEM }
Utilisation de la classe Etudiant q L’utilisation d’une classe ne pourra se faire que depuis une autre méthode puisque, en Java, toute instruction appartient toujours à une méthode. Mais il pourra s’agir de la méthode particulière main, et c’est ainsi que nous procéderons dans notre exemple de programme complet. Ø La démarche : À l’intérieur d’une méthode quelconque, une déclaration telle que : Etudiant e ; est tout à fait correcte. Cependant, contrairement à la déclaration d’une variable d’un type primitif (comme int n ; ), elle ne réserve pas d’emplacement pour un objet de type Etudiant, mais seulement un emplacement pour une référence à un objet de type Etudiant. L’emplacement pour l’objet proprement dit sera alloué sur une demande explicite du programme, en faisant appel à un opérateur unaire nommé new. Ainsi, l’expression : new Etudiant() // attention à la présence des parenthèses ( crée un emplacement pour un objet de type Etudiant et fournit sa référence en résultat. Par exemple, on pourra procéder à cette affectation : a = new Etudiant() ; // crée d’un objet de type Etudiant et place sa référence dans a 33 LICENCE LMD 2 eme année - Abdelkader ALEM
Utilisation de la classe Etudiant q La situation peut être schématisée ainsi : ? ? e ? nom age adresse q. Une fois qu’une référence à un objet a été convenablement initialisée, on peut appliquer n’importe quelle méthode à l’objet correspondant. Par exemple, on pourra appliquer la méthode initialise à l’objet référencé par e, en procédant ainsi : e. initialise (mohamed, 25, Tiaret) ; // appelle la méthode initialise du type Etudiant // en l’appliquant à l’objet de référence e, et // en lui transmettant les arguments Mohamed, 25 et Tiaret Remarque : Nous dirons que a est une variable de type classe. Nous ferons souvent l’abus de langage consistant à appeler objet a l’objet dont la référence est contenue dans a. 34 LICENCE LMD 2 eme année - Abdelkader ALEM
Utilisation de la classe Etudiant q Exemple: Comme nous l’avons déjà dit, nous pouvons employer notre classe Etudiant depuis toute méthode d’une autre classe, ou depuis une méthode main. A priori, nous pourrions faire de main une méthode de notre classe Etudiant. Mais la démarche serait alors trop particulière. nous préférons donc qu’elle appartienne à une autre classe. Voici un exemple complet d’une classe nommée Tst. Point contenant (seulement) une fonction main utilisant notre classe Etudiant: public class Tst. Etud { public static void main (String args[]) { Etudiant e 1 = new Etudiant ('Mohamed', ‘Tiaret’, ‘ 20’) ; e 1. affiche() ; Etudiant e 2 = new Etudiant (‘amine’, ‘Alger’, ‘ 21’) ; e 2. affiche() ; String c=’’ Tiare’’ e 2. Change. Adresse(c) ; e 2. affiche() ; } } LICENCE LMD 2 eme année - Abdelkader ALEM 35
Mise en œuvre d’un programme comportant plusieurs classes q Jusqu’ici, nos programmes étaient formés d’une seule classe. Il suffisait de la compiler et de lancer l’exécution. Avec plusieurs classes, les choses sont légèrement différentes et plusieurs démarches sont possibles: ØUn fichier source par classe. §Chaque classe doit être enregistré dans un fichier qui porte le nom de la classe § exemple: Etudiant. java, Tst. Etud. java ØPlusieurs classes dans un même fichier source § En fait, Java n’est pas tout à fait aussi strict. Il vous impose seulement de respecter les contraintes suivantes : • un fichier source peut contenir plusieurs classes mais une seule doit être publique • la classe contenant la méthode main doit obligatoirement être publique, afin que la machine virtuelle y ait accès ; • une classe n’ayant aucun attribut d’accès reste accessible à toutes les classes du même paquetage donc, dans ce cas du même fichier source. LICENCE LMD 2 eme année - Abdelkader ALEM 36
La notion de constructeur q Un constructeur n’est rien d’autre Øqu’une méthode, sans valeur de retour, portant le même nom que la classe. Ø Il peut disposer d’un nombre quelconque d’arguments; q Exemple de classe comportant un constructeur Considérons la classe Etudiant présentée précedemment et transformons simplement la méthode initialise en un constructeur en la nommant Etudiant. La définition de notre nouvelle classe se présente alors ainsi : class Etudiant { public Etudiant (String n, String a, Int g) // constructeur { nom = c ; adresse = a ; age= g ; } public void affiche () { … } public void Change. Adresse (String adr) {…} … } LICENCE LMD 2 eme année - Abdelkader ALEM 37
La notion de constructeur q Quelques règles concernant les constructeurs 1. un constructeur ne fournit aucune valeur. Dans son en-tête, aucun type ne doit figurer devant son nom. Même la présence (logique) de void est une erreur : class Truc {. . . public void Truc () // erreur de compilation : void interdit ici {. . . } } 2. Une classe peut ne disposer d’aucun constructeur (c’était le cas de notre première classe Etudiant). On peut alors instancier des objets comme s’il existait un constructeur par défaut sans arguments (et ne faisant rien) par des instructions telles que : Etudiant e = new Etudiant() ; // OK si Etudiant n’a pas de constructeur LICENCE LMD 2 eme année - Abdelkader ALEM 38
La notion de constructeur q Quelques règles concernant les constructeurs - Mais dès qu’une classe possède au moins un constructeur ce pseudoconstructeur par défaut ne peut plus être utilisé, comme le montre cet exemple : class A { public A(int) {. . . } // constructeur à un argument int. . . }. . . A a 1 = new A(5) ; // OK A a 2 = new A() ; // erreur - On notera que l’emploi d’un constructeur sans arguments ne se distingue pas de celui du constructeur par défaut. Si, pour une classe T donnée, l’instruction suivante est acceptée : T t = new T() ; cela signifie simplement que : • soit T ne dispose d’aucun constructeur, • soit T dispose d’un constructeur sans arguments. LICENCE LMD 2 eme année - Abdelkader ALEM 39
La notion de constructeur q Quelques règles concernant les constructeurs 3. Un constructeur ne peut pas être appelé directement depuis une autre méthode. Par exemple, si Etudiant dispose d’un constructeur à 3 arguments : Etudiant e = new Etudiant (ali, 25, Alger) ; . . . e. Etudiant (ali, 25, Alger); // interdit 4. Un constructeur peut appeler un autre constructeur de la même classe. Cette possibilité utilise la surdéfinition des méthodes et nécessite l’utilisation du mot-clé super ; nous en parlerons plus loin. 5. Un constructeur peut être déclaré privé (private). Dans ce cas, il ne pourra plus être appelé de l’extérieur, c’est-à-dire qu’il ne pourra pas être utilisé pour instancier des objets : class A { private A() {. . . } // constructeur privé sans arguments. . . }. . . A a() ; // erreur : le constructeur correspondant A() est privé LICENCE LMD 2 eme année - Abdelkader ALEM 40
La notion de constructeur q Construction et initialisation d’un objet Ø la création d’un objet entraîne toujours, par ordre chronologique, les opérations suivantes : • une initialisation par défaut de tous les champs de l’objet • une initialisation explicite lors de la déclaration du champ, • l’exécution des instructions du corps du constructeur. Ø Initialisation par défaut des champs d’un objet: Dès qu’un objet est créé, et avant l’appel du constructeur, ses champs sont initialisés à une valeur par défaut "nulle" ainsi définie : LICENCE LMD 2 eme année - Abdelkader ALEM 41
La notion de constructeur q Construction et initialisation d’un objet Ø Initialisation explicite lors de la déclaration du champ: Une variable locale peut être initialisée lors de sa déclaration. Il en va de même pour un champ. Considérons : class A { public A (. . . ) {. . . } // constructeur de A. . . private int n = 10 ; private int p ; } L’instruction suivante : A a = new A (. . . ) ; entraîne successivement : • l’initialisation (implicite) des champs n et p de a à 0, • l’initialisation (explicite) du champ n à la valeur figurant dans sa déclaration, soit 10, • l’exécution des instructions du constructeur. LICENCE LMD 2 eme année - Abdelkader ALEM 42
La notion de constructeur q Construction et initialisation d’un objet Ø Appel du constructeur Le corps du constructeur n’est exécuté qu’après l’initialisation par défaut et l’initialisation explicite. Voici un exemple d’école dans lequel cet ordre a de l’importance : public class Init { public static void main (String args[]) { A a = new A() ; // ici a. n vaut 5, a. p vaut 10, mais a. np vaut 200 a. affiche() ; }} class A { public A() { // ici, n vaut 20, p vaut 10 et np vaut 0 np = n * p ; n=5; } public void affiche() { System. out. println ("n = " + n + ", p = " + p + ", np = " + np) ; } private int n = 20, p = 10 ; private int np ; } // le résultat n = 5, p = 10, np = 200 LICENCE LMD 2 eme année - Abdelkader ALEM 43
La notion de constructeur q Construction et initialisation d’un objet Ø Cas des champs déclarés avec l’attribut final déclarer une variable locale avec l’attribut final. Dans ce cas, sa valeur ne devait être définie qu’une seule fois. Cette possibilité se transpose aux champs d’un objet. Examinons quelques exemples, EXEMPLE 1 class A {. . . private final int n = 20 ; // la valeur de n est définie dans sa déclaration. . . } - Ici, la valeur de n est une constante fixée dans sa déclaration. Notez que tous les objets de type A posséderont un champ n contenant la valeur 10 LICENCE LMD 2 eme année - Abdelkader ALEM 44
La notion de constructeur q Construction et initialisation d’un objet Ø Cas des champs déclarés avec l’attribut final EXEMPLE 2 class A { public A() { n = 10 ; } private final int n ; } § Ici, la valeur de n est définie par le constructeur de A. On a affaire à une initialisation tardive, comme pour une variable locale. § Ici encore, telle que la classe A a été définie, tous les objets de type A auront un champ n comportant la même valeur LICENCE LMD 2 eme année - Abdelkader ALEM 45
La notion de constructeur q Construction et initialisation d’un objet Ø Cas des champs déclarés avec l’attribut final EXEMPLE 3 Considérez maintenant : class A { public A(int nn) { n = nn ; } private final int n ; } §Cette fois, les différents objets de type A pourront posséder des valeurs de n différentes. LICENCE LMD 2 eme année - Abdelkader ALEM 46
La notion de constructeur q Construction et initialisation d’un objet Ø Cas des champs déclarés avec l’attribut final Quelques règles - Comme une variable locale, un champ peut donc être déclaré avec l’attribut final, afin d’imposer qu’il ne soit initialisé qu’une seule fois. Toute tentative de modification ultérieure conduira à une erreur de compilation - Un champ déclaré final doit être initialisé au plus tard par un constructeur (ce qui est une bonne précaution). - D’autre part, il n’est pas permis de compter sur l’initialisation par défaut d’un tel champ. Le schéma suivant conduira à une erreur de compilation : class A { A() { // ici, on ne donne pas de valeur à n } private final int n ; // ici, non plus --> erreur de compilation } LICENCE LMD 2 eme année - Abdelkader ALEM 47
La notion de destructeur q Un destructeur permet d'exécuter du code lors de la libération de la place mémoire occupée par l'objet. q En C++ ØL’opérateur delete permet de détruire un objet (dynamique) créé par new. Les objets automatiques sont automatiquement détruits lors de la sortie du bloc correspondant. La destruction d’un objet (dynamique ou automatique) entraîne l’appel d’une méthode particulière dite destructeur. q EN JAVA Ø il n’existe aucun opérateur permettant de détruire un objet dont on n’aurait plus besoin. 2014/2015 LICENCE LMD 2 eme année - Abdelkader ALEM 48
La notion de destructeur q EN JAVA En fait, la démarche employée par Java est un mécanisme de gestion automatique de la mémoire connu sous le nom de ramassse-miettes (en anglais Garbage Collector). Son principe est le suivant : Ø À tout instant, on connaît le nombre de références à un objet donné. On notera que cela n’est possible que parce que Java gère toujours un objet par référence. Ø Lorsqu’il n’existe plus aucune référence sur un objet, on est certain que le programme ne pourra plus y accéder. Il est donc possible de libérer l’emplacement correspondant, qui pourra être utilisé pour autre chose. Ø Cependant, pour des questions d’efficacité, Java n’impose pas que ce travail de récupération se fasse immédiatement. En fait, on dit que l’objet est devenu candidat au ramasse-miettes. LICENCE LMD 2 eme année - Abdelkader ALEM 49
La notion de destructeur q EN JAVA Remarque §On peut créer un objet sans en conserver la référence, comme dans cet exemple artificiel : (new Point(3, 5)). affiche() ; §Ici, on crée un objet dont on affiche les coordonnées. Dès la fin de l’instruction, l’objet (qui n’est pas référencé) devient candidat au ramasse -miettes. §Avant qu’un objet soit soumis au ramasse-miettes, Java appelle la méthode finalize de sa classe. En théorie, on pourrait se fonder sur cet appel pour libérer des ressources qui ne le seraient pas automatiquement. En pratique, cependant, on est fortement limité par le fait qu’on ne maîtrise pas le moment de cet appel. Dans bon nombre de cas d’ailleurs, le ramasse-miettes ne se déclenche que lorsque la mémoire commence à se faire rare. . . LICENCE LMD 2 eme année - Abdelkader ALEM 50
Typologie des méthodes d’une classe q Parmi les différentes méthodes que comporte une classe, on a souvent tendance à distinguer : Ø les constructeurs ; Øles méthodes d’accès (en anglais accessor) qui fournissent des informations relatives à l’état d’un objet, c’est-à-dire aux valeurs de certains de ses champs (généralement privés), sans les modifier ; Les accesseur Ø les méthodes d’altération (en anglais mutator) qui modifient l’état d’un objet, donc les valeurs de certains de ses champs; les modificateurs Ø Par convention, les accesseurs en lecture commencent par get et les modificateur commencent par set LICENCE LMD 2 eme année - Abdelkader ALEM 51
Typologie des méthodes d’une classe q Exemple : private int valeur = 13; public int get. Valeur(){ return(valeur); } public void set. Valeur(int val){ valeur = val; } LICENCE LMD 2 eme année - Abdelkader ALEM 52
Affectation et comparaison d’objets q Nous avons étudié le rôle de l’opérateur d’affectation sur des variables d’un type primitif. Par ailleurs, nous venons de voir qu’il existe des variables de type classe, destinées à contenir des références sur des objets. Comme on peut s’y attendre, ces variables pourront être soumises à des affectations. Mais celles-ci portent sur les références et non sur les objets eux-mêmes, ce qui modifie quelque peu la sémantique (signification) de l’affectation. C’est ce que nous allons examiner à partir de deux exemples: q Exemple 1 Supposons que nous disposions d’une classe Point possédant un constructeur à deux arguments entiers et considérons ces instructions : Point a, b ; . . . a = new Point (3, 5) ; b = new Point (2, 0) ; Après leur exécution, on aboutit à cette situation : LICENCE LMD 2 eme année - Abdelkader ALEM 53
Celle-ci recopie simplement dans a la référence contenue dans. Affectation b, ce qui nous conduit à: et comparaison d’objets Dorénavant, a et b désignent le même objet, et non pas deux objets de même valeur. : 2014/2015 LICENCE LMD 2 eme année - Abdelkader ALEM 54
Affectation et comparaison d’objets q Exemple 2 Considérons les instructions suivantes : Point a, b, c ; . . . a = new Point (1, 10) ; b = new Point (2, 20) ; c=a; a=b; b=c; Après leur exécution, on aboutit à cette situation : Remarque Le fait qu’une variable de type classe soit une référence et non une valeur aura aussi des conséquences dans la transmission d’un objet en argument d’une méthode. : LICENCE LMD 2 eme année - Abdelkader ALEM 55
Affectation et comparaison d’objets q. La notion de clone Nous venons de voir que l’affectation de variables de type objet se limite à la recopie de références. Elle ne provoque pas la recopie de la valeur des objets. Si on le souhaite, on peut bien entendu effectuer explicitement la recopie de tous les champs d’un objet dans un autre objet de même type. la démarche la plus réaliste consiste plutôt à prévoir dans la classe correspondante une méthode destinée à fournir une copie de l’objet concerné, comme dans cet exemple: class A { public A(abs, int ord) { x = abs ; y = ord ; } public A-copie () // renvoie une référence à un objet de type A { A a = new A(x, y) ; a. x = x ; a. y = y ; return a ; } private int x, y ; }. . . A a = new A(1, 2) ; A b = a. copie() ; // b est une copie conforme de a LICENCE LMD 2 eme année - Abdelkader ALEM 56
Affectation et comparaison d’objets q. La notion de clone Cette démarche est utilisable tant que la classe concernée ne comporte pas de champs de type classe. Dans ce cas, il faut décider si leur copie doit, à son tour, porter sur les objets référencés plutôt que sur les références. On voit apparaître la distinction usuelle entre : Ø la copie superficielle d’un objet : on se contente de recopier la valeur de tous ses champs, y compris ceux de type classe, Ø la copie profonde d’un objet : comme précédemment, on recopie la valeur des champs d’un type primitif mais pour les champs de type classe, on crée une nouvelle référence à un autre objet du même type de même valeur. § la copie profonde peut être récursive; § La démarche la plus rationnelle pour traiter cette copie profonde qu’on nomme clonage en Java, consiste à faire en sorte que chaque classe concernée par l’éventuelle récursion dispose de sa propre méthode LICENCE LMD 2 eme année - Abdelkader ALEM 57
L’encapsulation q. L’encapsulation est la possibilité de ne montrer de l’objet que ce qui est nécessaire à son utilisation. q. L’encapsulation permet d’offrir aux utilisateurs d’une classe la liste des méthodes et éventuellement des attributs utilisables depuis l’extérieur. Cette liste de services exportables est appelée l’interface de la classe et elle est composée d’un ensemble des méthodes et d’attributs dits publics (Public). q. Les méthodes et attributs réservés à l’implémentation des comportements internes à l’objet sont dits privés (Private). Leur utilisation est exclusivement réservée aux méthodes définies dans la classe courante. q. Les avantages de l’encapsulation sont : ØSimplification de l’utilisation des objets, ØMeilleure robustesse du programme, ØSimplification de la maintenance globale de l’application LICENCE LMD 2 eme année - Abdelkader ALEM 58
Modificateurs de visibilité et Accès q. Modificateurs de visibilité Les attributs et les méthodes sont précédés lors de la déclaration par l’un des modificateurs de visibilité « public» , « private» , « protected» et Néant suivants: §Une méthode, classe ou attribut sont déclarés comme publiques « public» s’ils doivent être visibles à l’intérieur et à l’extérieur quelque soit leur package. §Une méthode, classe ou attribut ne sont pas précédés par un modificateur de visibilité explicite (Néant) ne vont être visibles qu’à l’intérieur de même package. C'est-à-dire seules classes de même package peuvent accéder aux attributs et méthodes de classes « amies» . Ce modificateur de visibilité est aussi appelé «modificateur de package» ou modificateur «freindly» . LICENCE LMD 2 eme année - Abdelkader ALEM 59
Modificateurs de visibilité et Accès q. Modificateurs de visibilité §Une méthode ou attributs définis comme étant privés « private» s’ils sont accessibles uniquement par les méthodes de la classe en cours. Ils ne sont pas accessibles ailleurs. §Une méthode ou attribut sont définis comme protégés « protected» s’ils ne peuvent être accessibles qu’à travers les classes dérivées ou les classes de même package. LICENCE LMD 2 eme année - Abdelkader ALEM 60
Modificateurs de visibilité et Accès q Tableaux récapitulatifs des droits d’accès Ø Modificateurs d’accès des classes et interfaces LICENCE LMD 2 eme année - Abdelkader ALEM 61
Modificateurs de visibilité et Accès q Tableaux récapitulatifs des droits d’accès Ø Modificateurs d’accès pour les membres et les classes internes LICENCE LMD 2 eme année - Abdelkader ALEM 62
Modificateurs de visibilité et Accès q Accès aux membres privés Ø Pour accéder aux attributs de l’intérieur de la classe, il suffit d’indiquer le nom de l’attribut que l’on veut y accéder. Ø-Pour accéder de l’extérieur de la classe, on utilise la syntaxe suivante: <nom_méthode>. <nom_attribut> q. Exemple 1 Si longueur et largeur étaient des attributs publics de Rectangle, on peut écrire le code suivant dans la méthode «main» de la classe Test_Rectangle r = new Rectangle (); r. longueur = 20; r. largeur = 15; int la = r. longueur 63 LICENCE ; LMD 2 eme année - Abdelkader ALEM
Modificateurs de visibilité et Accès q. Exemple 1 Si longueur et largeur étaient des attributs privés « private» , les instructions suivantes seront refusées par le compilateur r. longueur = 20; //faux r. largeur = 15; //faux int la = r. longueur ; //faux Il fallait dans le deuxième cas définir des méthodes d’accés « setlong (int)» et «setlarg (int)» qui permettent de modifier les valeurs des attributs et les méthodes d’accès « getlong()» et « getlarg()» pour retourner les valeurs de longueur et de largeur d’un objet Rectangle. Dans ce cas, les instructions seront les suivantes: r. setlong(20); //juste r. setlarg(15); //juste int la = r. getlong() ; //juste LICENCE LMD 2 eme année - Abdelkader ALEM 64
Modificateurs de visibilité et Accès q. Exemple 2 public class Rectangle { Private int longueur; private int larg; Rectangle (int l, int a) //Le premier constructeur {longueur= l; larg= a; } Rectangle() // Le deuxième constructeur {longueur= 20; larg= 10; } Rectangle (int x) //Le troisième constructeur {longueur= 2*x; larg= x; } int getlong ()//pour retourner la valeur de longueur {return (longueur); } qint getlarg () //Pour retourner la largeur {return (larg); } LICENCE LMD 2 eme année - Abdelkader ALEM 65
Modificateurs de visibilité et Accès q. Exemple 2 (suite) void setlong (int l) //pour modifier la longueur {longueur=l; } void setlarg (int l) //pour modifier la largeur {larg=l; } int surface() //Pour calculer la surface {return(longueur*larg); } int périmètre() //pour calculer le périmètre { return((larg+longueur)*2); } void allonger(int l) //Pour allonger la longueur d’un rectangle { longueur+=l; } void affiche() //pour afficher les caractéristiques d’un rectangle { System. out. println("Longueur=" + longueur + " Largeur =" + larg ); } } LICENCE LMD 2 eme année - Abdelkader ALEM 66
Modificateurs de visibilité et Accès q. Exemple 2 (suite) Code de la classe Test_Rect class Test_Rec { public static void main(String []args) { Rectangle r = new Rectangle(10, 5); Rectangle r 3; r 3= new Rectangle (14); Rectangle r 2 = new Rectangle(); r. affiche(); r 2. affiche(); r 3. affiche(); r 2. setlong(50); r 2. setlarg(30); r 2. affiche(); System. out. println("Rectangle 1" ); System. out. println("Surface= " + r. surface()); System. out. println("Périmetre= " + r. perimetre()); r. allonger(40); System. out. println("Aprés allongement"); r. affiche(); } LICENCE LMD 2 eme année - Abdelkader ALEM 67
Chapitre 3: Héritage et polymorphisme LICENCE LMD 2 eme année - Abdelkader ALEM 68
Introduction 1. Introduire la technique d’héritage : intérêt et notation 2. Introduire les droits d’accès d’une classe dérivée aux membres de la classe de base 3. Comprendre la construction d’un objet dérivé 4. Maîtriser la notion de redéfinition 5. Découvrir le concept de dérivations multiples LICENCE LMD 2 eme année - Abdelkader ALEM 69
Héritage q Le principe de l'héritage q L'héritage est un mécanisme qui facilite la réutilisation du code et la gestion de son évolution; q Grâce à l'héritage, les objets d'une classe ont accès aux données et aux méthodes de la classe parent et peuvent les étendre; q Les sous classes peuvent redéfinir les variables et les méthodes héritées. Pour les : Ø variables, il suffit de les redéclarer sous le même nom avec un type différent. Ø Les méthodes sont redéfinies avec le même nom, les mêmes types et le même nombre d'arguments LICENCE LMD 2 eme année - Abdelkader ALEM 70
Héritage q Le principe de l'héritage q L'héritage successif de classes permet de définir une hiérarchie de classe qui ce compose de super classes et de sous classes; q Une classe qui hérite d'une autre est une sous classe et celle dont elle hérite est une super_classe; q Une classe peut avoir plusieurs sous classes; q Une classe ne peut avoir qu'une seule classe mère : il n'y a pas d'héritage multiple en java; q Object est la classe parente de toutes les classes en java. Toutes les variables et méthodes contenues dans Object sont accessibles à partir de n'importe quelle classe car par héritage successif toutes les classes héritent d'Object. LICENCE LMD 2 eme année - Abdelkader ALEM 71
Héritage q Syntaxe class. Fille extends class. Mere {. . . } q On utilise le mot clé extends pour indiquer qu'une classe hérite d'une autre. En l'absence de ce mot réservé associé à une classe, le compilateur considère la classe Object comme classe parent. q Exemple //Classe de base class graphique { private int x, y; graphique (int x, int y) {this. x = x ; this. y = y ; } void affiche () { System. out. println (`` Le centre de l’objet se trouve dans : » + x + « et » + y) ; } double surface () {return (0); } } // fin de la classe graphique LICENCE LMD 2 eme année - Abdelkader ALEM 72
Héritage q Exemple (suite) //Classe dérivée 1 class Cercle extends graphique { private double rayon =1 ; void affiche () { Sustem. out. println ( «C’est un cercle de rayon » + rayon) ; Super. affiche (); } double surface () {return (rayon * 2* 3. 14) ; } } //Classe dérivée 2 class Rectangle extends graphique { private int larg, longueur ; Rectangle ( int x, int y, int l 1, int l 2) {super (x, y) ; longueur = l 1 ; larg = l 2 ; } double surface () {return (longueur*largeur) ; } }// fin de la classe Rectangle LICENCE LMD 2 eme année - Abdelkader ALEM 73
Héritage q Interprétation d’exemple 1. Dans cet exemple, la classe Cercle hérite de la classe graphique les attributs et les méthodes, redéfinit les deux méthodes surface et affiche et ajoute l’attribut rayon. 2. La classe Rectangle redéfinit la méthode surface et ajoute les attributs longueur et larg Remarques: Le concept d’héritage permet à la classe dérivée de: 1. Hériter les attributs et les méthodes de la classe de base. 2. Ajouter ses propres définitions des attributs et des méthodes. 3. Redéfinir et surcharger une ou plusieurs méthodes héritées. 4. Tout objet peut être vu comme instance de sa classe et de toutes les classes dérivées. 5. Toute classe en Java dérive de la classe Object. 6. Toute classe en Java peut hériter directement d’une seule classe de base. Il n’y a pas la notion d’héritage multiple en Java, mais il peut être implémenté via d’autres moyens tels que les interfaces LICENCE LMD 2 eme année - Abdelkader ALEM 74
Héritage q Pour invoquer une méthode d'une classe parent, il suffit d'indiquer la méthode préfixée par super. q Pour appeler le constructeur de la classe parent il suffit d'écrire super(paramètres) avec les paramètres adéquats. q Le lien entre une classe fille et une classe parent est géré par le langage : une évolution des règles de gestion de la classe parent conduit à modifier automatiquement la classe fille dès que cette dernière est recompilée. q En java, il est obligatoire dans un constructeur d'une classe fille de faire appel explicitement ou implicitement au constructeur de la classe mère. LICENCE LMD 2 eme année - Abdelkader ALEM 75
Héritage q L'accès aux propriétés héritées q Les variables et méthodes définies avec le modificateur d'accès public restent publiques à travers l'héritage et toutes les autres classes. q Une variable d'instance définie avec le modificateur private est bien héritée mais elle n'est pas accessible directement, elle peut l’être via les méthodes héritées. q Si l'on veut conserver pour une variable d'instance une protection semblable à celle assurée par le modificateur private, il faut utiliser le modificateur protected. La variable ainsi définie sera hérité dans toutes les classes descendantes qui pourront y accéder librement mais ne sera pas accessible hors de ces classes directement. LICENCE LMD 2 eme année - Abdelkader ALEM 76
Héritage q L'accès aux propriétés héritées Ø Exemple 1: La classe dérivée et la classe de base sont dans le même package Formes_geo ; class graphiques { private x, y; public String couleur ; void affiche () { System. out. println ( « Le centre de l’objet = (» + x + «, » + y + «) » ); } double surface ( ) {return (0); } } //fin de la classe graphiques LICENCE LMD 2 eme année - Abdelkader ALEM 77
Héritage q L'accès aux propriétés héritées Ø Exemple 1: La classe dérivée et la classe de base sont dans le même package Formes_geo ; class cercle extends graphiques{ double rayon; void changer_centre ( int x 1, int y 1, double r) {x = x 1; y = y 1; // faux car x et y sont déclarés private dans la classe de base rayon =r; public double surface ( ) {return (rayon * 2* 3. 14); } public void affichec () {affiche (); // juste car le modificateur de visibilité de ce membre est freindly System. out. println ( « Le rayon = » + rayon + «La couleur = « + couleur ) ; } } LICENCE LMD 2 eme année - Abdelkader ALEM 78
Héritage q L'accès aux propriétés héritées Ø Exemple 1 (Interprétation): Ø Dans le premier cas, la classe dérivée est la classe de base sont dans le même package, donc la classe cercle a pu accéder aux membres (attributs et méthodes) publiques (l’attribut couleur), Ø de même elle a pu accéder aux membres «freindly» c'est-àdire qui n’ont pas un modificateur de visibilité (la méthode affiche), Ø mais elle n’a pas pu accéder aux membres privés (x et y). LICENCE LMD 2 eme année - Abdelkader ALEM 79
Héritage q L'accès aux propriétés héritées (suite) Ø Exemple 2: les deux classes ne sont pas dans le même package Formes_geo ; class graphiques { private x, y; public String couleur ; void affiche () { System. out. println ( « Le centre de l’objet = (» + x + «, » + y + «) » ); } double surface ( ) {return (0); } } //fin de la classe graphiques package Formes. Circ ; class cercle extends graphiques{ double rayon; void changer_centre ( int x 1, int y 1, double r) {x = x 1; y = y 1; // faux car x et y sont déclarés private dans la classe de base rayon =r; public double surface ( ) {return (rayon * 2* 3. 14); } public void affichec () {affiche (); // FAUX car le modificateur de visibilité de ce membre est freindly System. out. println ( « Le rayon = » + rayon + «La couleur = « + couleur ) ; } } LICENCE LMD 2 eme année - Abdelkader ALEM 80
Héritage q L'accès aux propriétés héritées (suite) Ø Exemple 2: (Interprétation): § Dans le deuxième cas, la classe dérivée est la classe de base ne sont pas dans le même package, donc la classe cercle a pu accéder aux membres (attributs et méthodes) publiques (l’attribut couleur), § mais, elle n’a pas pu accéder aux membres « freindly» c'est-àdire qui n’ont pas un modificateur de visibilité (la méthode affiche) et aux membres privés (x et y). § Nous avons déjà vu qu’il existe 3 types de modificateurs de visibilité publiques ( «public» ), privés (private) et de paquetage ou freindly (sans mention). § Il existe encore un quatrième droit d’accès dit protégé (mot clé « protected» ). LICENCE LMD 2 eme année - Abdelkader ALEM 81
Héritage q Construction et initialisation des objets dérivés Ø En java, le constructeur de la classe dérivée doit prendre en charge l’intégralité de la construction de l’objet. Ø Si un constructeur d’une classe dérivée appelle un constructeur d’une classe de base, il doit obligatoirement s’agir de la première instruction du constructeur. Ø Le constructeur de la classe de base est désigné par le mot clé «super» LICENCE LMD 2 eme année - Abdelkader ALEM 82
Héritage q Construction et initialisation des objets dérivés Ø Remarque § Dans le cas général, une classe de base et une classe dérivée possèdent chacune au moins un constructeur. § Le constructeur de la classe dérivée complète la construction de l’objet dérivé, et ce, en appelant en premier lieu le constructeur de la classe de base. Ø Toutefois, il existe des cas particuliers qui sont: § Cas 1: La classe de base ne possède aucun constructeur § Cas 2: La classe dérivée ne possède pas un constructeur LICENCE LMD 2 eme année - Abdelkader ALEM 83
Héritage q Construction et initialisation des objets dérivés (suite) Ø Cas 1: La classe de base ne possède aucun constructeur Dans ce cas, si la classe dérivée veut définir son propre constructeur, elle peut optionnellement appeler dans la première instruction de constructeur la clause « super () » pour désigner le constructeur par défaut de la classe de base. Exemple 1 (cas 1) Class A { // pas de constructeur } class B extends A { public B(…. ) {super() ; //appel de constructeur par défaut de A ……… } B b = new B(…); // Appel de constructeur 1 de A LICENCE LMD 2 eme année - Abdelkader ALEM 84
Héritage q Construction et initialisation des objets dérivés (suite) Ø Cas 2: La classe dérivée ne possède pas un constructeur Dans ce cas, le constructeur par défaut de la classe dérivée doit initialiser les attributs de la classe dérivée et appeler: 1. Le constructeur par défaut de la classe de base si elle ne possède aucun constructeur. 2. Le constructeur sans argument si elle possède au moins un constructeur. 3. Dans le cas où il n’ y a pas un constructeur sans argument et il y a d’autres constructeurs avec arguments, le compilateur génère des erreurs. LICENCE LMD 2 eme année - Abdelkader ALEM 85
Héritage q Construction et initialisation des objets dérivés (suite) • Exemple 3 Exemple 2 Exemple 1 (cas 3) (cas 2) (cas 1) • • • Class A { public // pas de A() A constructeur ( int {…. } n) //constructeur 1 {…. . } //constructeur 1 }public A ( int n) {…. . } //constructeur 2 } class B extends A { class // public …. . pas BB(…. ) extends de constructeur A{ }// {super() …. . pas; de //appel constructeur de constructeur par défaut de A }……… B b = new B(); B /* } b. On = new obtient B(); une // Appel erreur dede constructeur 1 compilation de car. AA ne dispose pas B b = new B(…); // Appel de constructeur 1 de A un constructeurs sans argument et possède un autre constructeur*/ LICENCE LMD 2 eme année - Abdelkader ALEM 86
Héritage q Construction et initialisation des objets dérivés (suite) • Exemple 4 (cas 1 et 2) • • Class A { //pas de constructeurs } class B extends A { //pas de constructeurs } B b = new B (); // Appel de constructeur par défaut de B qui Appelle le constructeur par /défaut de A. LICENCE LMD 2 eme année - Abdelkader ALEM 87
Héritage q Dérivations successives Ø D’une même classe peuvent être dérivées plusieurs classes différentes. Ø Les notions de classe de base et de classe dérivée sont relatives puisqu’une classe dérivée peut, à son tour servir de base pour une autre classe. Autrement dit, on peut rencontrer des situations telles que: Ø La classe Caniche est une classe descendante directement de la classe Chien et une classe descendante de Animal Ø La notion de l’héritage multiple n’existe pas directement en Java, mais elle peut être implémentée via la notion des interfaces LICENCE LMD 2 eme année - Abdelkader ALEM 88
Héritage q Redéfinition et surcharge de membres Ø La notion de surcharge (surdéfinition) de méthode correspond à des méthodes de même nom, mais de signatures différentes. Ø Dans le cadre de l’héritage: une classe dérivée pourra à son tour surcharger une méthode d’une classe ascendante. Bien entendu, la ou les nouvelles méthodes ne deviendront utilisables que par la classe dérivée ou ses descendantes, mais par ses ascendantes. Ø De même une classe dérivée peut fournir une nouvelle définition d’une méthode de même nom et aussi de même signature et de même type de retour (Redéfinition). =>Alors que la surcharge cumule plusieurs méthodes de même nom, la redéfinition substitue une méthode à une autre. LICENCE LMD 2 eme année - Abdelkader ALEM 89
Héritage q Redéfinition d’une méthode q La redéfinition d'une méthode héritée doit impérativement conserver la déclaration de la méthode parent (type et nombre de paramètres, la valeur de retour et les exceptions propagées doivent être identiques) et fournir dans une sous-classe une nouvelle implémentation de la méthode. q Cette nouvelle implémentation masque alors complètement celle de la super-classe. q Si la signature de la méthode change, ce n'est plus une redéfinition mais une surcharge. q Remarques La re-déclaration doit être strictement identique à celle de la super-classe : même nom, même paramètres et même type de retour. q Grâce au mot-clé super, la méthode redéfinie dans la sous-classe peut réutiliser du code écrit dans la méthode de la super-classe, qui n’est plus visible autrement. LICENCE LMD 2 eme année - Abdelkader ALEM 90
Héritage q Redéfinition d’une méthode (Exemple) //Super-classe class graphiques { private x, y; public String couleur ; public void affiche () { System. out. println ( « Le centre de l’objet = (» + x + «, » + y + «) » ); } double surface ( ) {return (0); } } //fin de la classe graphiques //classe dérivée class cercle extends graphiques{ double rayon; public double surface ( ) { return (rayon * 2* 3. 14); } //redéfinition de «surface» public void affiche () //redéfinition de la méthode «affiche» {super. affiche (); // appel de affiche de la super-classe System. out. println ( « Le rayon = » + rayon + «La couleur = « + couleur ) ; } } LICENCE LMD 2 eme année - Abdelkader ALEM 91
Héritage q Redéfinition de méthode et dérivations successives Soit l’arborescence suivante: La présence d’un astérisque (*) signale la définition ou la redéfinition d’une méthode f L’appel de la fonction f conduira pour chaque classe à l’appel de la méthode indiquée: Classe A: Méthode f de A Classe B: Méthode f de A Classe C: Méthode f de C Classe D: Méthode f de D Classe E: Méthode f de A Classe F: Méthode f de C LICENCE LMD 2 eme année - Abdelkader ALEM 92
Héritage q Surcharge des méthodes En Java, une méthode dérivée peut surcharger une méthode d’une classe ascendante q Exemple Class A {public void f (int n) {…. . } …} Class B extends A {public void f (float n) {…. . } …} Aa, Bb; int n; float x; a. f(n) // appelle f(int) de A a. f(x) // Erreur, on a pas dans A f(float) b. f(n) // appelle f(int) de A b. f(x) // appelle f(float) de B LICENCE LMD 2 eme année - Abdelkader ALEM 93
Héritage q Utilisation simultanée de surcharge et de redéfinition Class A {public void f (int n) {…. . } public void f (float n) {…. . } …} Class B extends A {public void f (int n) {…. . } // redefinition de la méthode f( int ) de A public void f (double n) {…. . } // Surcharge de la méthode f de A et de B …} Aa, Bb; int n , float x, double y; a. f(n) ; //Appel de f(int) de A a. f(x); //Appel de f(float) de A a. f(y); //Erreur, il n’ y a pas f(double) dans A b. f(n) ; //Appel de f(int) de B car f(int) est redéfinie dans B b. f(x); //Appel de f(float) de A b. f(y); //Appel de f(double) de B LICENCE LMD 2 eme année - Abdelkader ALEM 94
Héritage q Règles générales de redéfinition Ø Si une méthode d’une classe dérivée a la même signature qu'une méthode d’une classe ascendante: § Les 2 méthodes doivent avoir le même type de retour. § Le droit d’accès de la méthode de la classe dérivée ne doit pas être moins élevé que celui de la classe ascendante. Ø Une méthode statique ne peut pas être redéfinie. LICENCE LMD 2 eme année - Abdelkader ALEM 95
Héritage q Autres mots clés «final» et «super» q Le mot clé «super» : Le mot clé «super» peut être utilisé pour: Ø appeler un constructeur de la classe de base dans le constructeur de la classe dérivée. Cet appel doit être la 1 instruction dans le constructeur de la classe dérivée. § Syntaxe: super (<liste des arguments>). . Ø Accéder dans une méthode d’une classe dérivée à une méthode de la super-classe(optionnel sauf dans le cas de redéfinition) § Syntaxe: super. nom_méthode (<liste des arguments>); Ø Accéder dans une méthode dérivée à un attribut de la classe de base (optionnel) § Syntaxe: super. nom_attribut LICENCE LMD 2 eme année - Abdelkader ALEM 96
Héritage q Le modificateur «final» Ø Cas 1: Le modificateur «final» placé devant une classe interdit sa dérivation Exemple final class A { //Méthodes et attributs } class B extends A //Erreur car la classe A est déclarée finale {//. . } Ø Cas 2: Le modificateur «final» placé devant une méthode permet d’interdire sa redéfinition Class A { final Public void f(int x) {…. . } //…Autres méthodes et attributs } Class B {…//Autres méthodes et attributs public void f (int x) {…} // Erreur car la méthode f est déclarée finale. Pas de redéfinition } LICENCE LMD 2 eme année - Abdelkader ALEM 97
Héritage q Des conseils sur l'héritage Lors de la création d'une classe « mère » il faut tenir compte des points suivants : Ø la définition des accès aux variables d'instances, très souvent privées, doit être réfléchie entre protected et private ; Ø pour empêcher la redéfinition d'une méthode (surcharge) il faut la déclarer avec le modificateur final. Ø Lors de la création d'une classe fille, pour chaque méthode héritée qui n'est pas final, il faut envisager les cas suivant : 1. la méthode héritée convient à la classe fille: on ne doit pas la redéfinir ; 2. la méthode héritée convient mais partiellement du fait de la spécialisation apportée par la classe fille: il faut la redéfinir voir la surcharger. La plupart du temps une redéfinition commencera par appeler la méthode héritée (via super) pour garantir l'évolution du code 3. la méthode héritée ne convient pas : il faut redéfinir ou surcharger la méthode sans appeler la méthode héritée lors de la redéfinition. LICENCE LMD 2 eme année - Abdelkader ALEM 98
Chapitre 3: (suite) Polymorphisme Classes Abstraites LICENCE LMD 2 eme année - Abdelkader ALEM 99
Polymorphisme q le polymorphisme est un concept très puissant de la programmation orientée objet qui complète l’héritage. q Il permet de manipuler des objets sans en connaître (tout à fait) le type. q Par exemple, on pourra construire un tableau d’objets (donc en fait de références à des objets), les uns étant de type Point, les autres étant de type Point. A (dérivé de Point) et appeler la méthode affiche pour chacun des objets du tableau. Chaque objet réagira en fonction de son propre type. q Le polymorphisme exploite la relation est induite par l’héritage en appliquant la règle suivante : un point. A est aussi un point, on peut donc bien le traiter comme un point, la réciproque étant bien sûr fausse. LICENCE LMD 2 eme année - Abdelkader ALEM 100
Polymorphisme q Les bases du polymorphisme Le polymorphisme en Java, se traduit par : Ø La compatibilité entre un type dérivée et un type ascendant. Ø La ligature dynamique des méthodes, dans le sens où il permet d’obtenir le comportement adapté à chaque type d’objet, sans avoir besoin de tester sa nature de quelque façon que ce soit. Ø Le polymorphisme se base sur cette affirmation: un objet a comme type non seulement sa classe mais aussi n’importe quelle classe dérivée LICENCE LMD 2 eme année - Abdelkader ALEM 101
Polymorphisme q Exemples et interprétations Ø Exemple 1 //Classe de base class graphique { private int x, y; public graphique ( int x, int y) { this. x = x; this. y = y; } public void identifie () { System. out. println ( « Je suis une forme géometrique» ) ; } public void affiche () { this. identifie(); System. out. println ( « Le centre de l’objet se trouve dans: » + x + « et » + y); } double surface () {return (0); } }// fin de la classe graphiqu LICENCE LMD 2 eme année - Abdelkader ALEM 102
Polymorphisme q Exemples et interprétations Ø Exemple 1 //Classe dérivée 1 class Cercle extends graphique { private double rayon =1; public Cercle ( int x, int y, double r) {super(x, y); rayon = r; } public void identifie () { System. out. println ( « Je suis un cercle » ) ; } double surface () {return ( rayon * 2* 3. 14); } } LICENCE LMD 2 eme année - Abdelkader ALEM 103
Polymorphisme q Exemples et interprétations Ø Exemple 1 //Classe dérivée 2 class Rectangle extendsgraphique { private int larg, longueur ; Rectangle ( int x, int y, int l 1, int l 2) {super (x, y); longueur = l 1; larg = l 2; } double surface () {return (longueur*largeur); } public void identifie() { System. out. println( « Je suis un rectangle» ); } }// fin de la classe Rectangle LICENCE LMD 2 eme année - Abdelkader ALEM 104
Polymorphisme q Exemples et interprétations Ø Exemple 1 //Classe de test class test_poly { public static void main (String [] args) { graphique g = new graphique (3, 7); g. identifie (); g= new Cercle (4, 8, 10) ; // compatibilité entre le type de la classe et de la classe dérivéé g. identifie(); g= new Rectangle (7, 9, 10, 3); // compatibilité entre le type de la classe et de la classe dérivéé g. identifie (); } } LICENCE LMD 2 eme année - Abdelkader ALEM 105
Polymorphisme q Exemples et interprétations Ø Résultat de l’exécution § Je suis une forme géométrique § Je suis un cercle § Je suis un rectangle Ø Interprétation § Le même identificateur « g» est initialisé dans la 1 instruction avec une référence de type « graphique» , § puis on a changé la référence de cette variable dans l’instruction 3 en lui affectant une référence de type « Cercle» , § puis dans l’instruction 5, on a changé sa référence avec une référence de classe dérivée « Rectangle» . LICENCE LMD 2 eme année - Abdelkader ALEM 106
Polymorphisme q Exemples et interprétations Ø Ces affectations confirment la compatibilité entre un type d’une classe de base et la référence d’une classe dérivée. Ø L’autre point qui semble plus important c’est la ligature dynamique des méthodes, dans le sens où le résultat de la méthode « identifie» a changé dans chaque appel selon le type effectif de la variable «g» . LICENCE LMD 2 eme année - Abdelkader ALEM 107
Polymorphisme q Exemple 2 Tableau des objets Dans cet exemple, on va exploiter les possibilités de polymorphisme pour créer un tableau hétérogène d’objets, c’est à dires dans lequel les éléments peuvent être de types différents. class test_poly 2 { public static void main (String [] args) { graphique [] tab = new graphique [6]; tab[0] = new graphique (3, 2); tab[1] = new Cercle (10, 7, 3); tab [2] = new Rectangle (4, 7, 8, 6); tab [3] = new graphique (8, 10); tab[4] = new Cercle (8, 5, 3); tab[5 = new Rectangle (10, 17, 3, 8); for (i=0 ; i <=5; i++) {tab[i]. affiche(); } } } LICENCE LMD 2 eme année - Abdelkader ALEM 108
Polymorphisme q Exemple 2 Tableau des objets Ø Résultat de l’exécution § § § Je suis une forme géométrique Le centre de l'objet se trouve dans : 3 et 2 Je suis un cercle Le centre de l'objet se trouve dans : 10 et 7 Je suis un rectangle Le centre de l'objet se trouve dans : 4 et 7 Je suis une forme géométrique Le centre de l'objet se trouve dans : 8 et 10 Je suis un cercle Le centre de l'objet se trouve dans : 8 et 5 Je suis un rectangle Le centre de l'objet se trouve dans : 10 et 17 LICENCE LMD 2 eme année - Abdelkader ALEM 109
Polymorphisme q Exemple 3 class test_poly 3 { public static void main (String [] args) { String c; graphique d; int c= Integer. parse. Int(args [0]) ; switch (c) { case 0 : d=new Cercle (10, 10); break; case 1: d=new Rectangle (10, 10, 10); break; case 2 : d= new graphique (10, 10); break; default: d= new graphique (0, 0); } d. identifie (); System. out. println ( « Surface =» + d. surface()); } LICENCE LMD 2 eme année - Abdelkader ALEM 110
Polymorphisme q Exemple 3 Résultat de l’exécution: Ø Le message affiché est en fonction de l’argument introduit dans la commande d’exécution. Ø Le gros avantage du polymorphisme est de pouvoir référencer des objets sans connaître à la compilation véritablement leur classe et de pouvoir par la suite à l’exécution lancer le code approprié à cet objet. Ø La liaison entre l’identificateur de la méthode polymorphe et son code est déterminée à l’exécution et non à la compilation, on parle alors de liaison dynamique. q Remarques Ø Ø Le polymorphisme se base essentiellement sur le concept d’héritage et la redéfinition des méthodes. Toutefois, si dans le même contexte d’héritage, on a à la fois une redéfinition et une surcharge de la même méthode, les règles de polymorphisme deviennent de plus en plus compliquées. La notion de polymorphisme peut être généralisée dans le cas de dérivations successives. LICENCE LMD 2 eme année - Abdelkader ALEM 111
Polymorphisme q Conversion des arguments effectifs : Ø La conversion d’un type dérivé en un type de base est aussi une conversion implicite légale, elle va donc être utilisée pour les arguments effectifs d’une méthode. Ø Exemples LICENCE LMD 2 eme année - Abdelkader ALEM 112
Polymorphisme q Conversion des arguments effectifs : class A {public void identifie() {System. out. println ( « Objet de type A» ) ; } } class B extends A {// pas de redéfinition de identitie ici} class Test { static void f(A a ) { a. identitie(); } } …. . A a = new A(); B b = new B (); Test. f(a); // OK Appel usuel; il affiche “objet de type A” Test. f(b); /*OK une référence à un objet de type B est compatible avec une référence à un objet de type A. L’appel a. identifie affiche: « Objet de type A» */ LICENCE LMD 2 eme année - Abdelkader ALEM 113
Polymorphisme q Conversion des arguments effectifs : Exemple 2 On va juste modifier le corps de la classe B par une redéfinition de la méthode «identifie» class B { public void identifie () { System. out. println ( « Objet de type B» ) ; } } …. A a = new A(); B b = new B (); Test. f (b); /*OK une référence à un objet de type B est compatible avec une référence à un objet de type A. L’appel a. identifie affiche: « Objet de type B» */ LICENCE LMD 2 eme année - Abdelkader ALEM 114
Polymorphisme q Conversion des arguments effectifs : Exemple 2 Cet exemple, montre que comme dans les situations d’affectation, la conversion implicite d’un type dérivé dans un type de base n’est pas dégradante puisque grâce au polymorphisme, c’est bien le type de l’objet référencé qui intervient. Remarque: Dans le cas où la méthode f est surdefinie, il y a encore des règles plus compliquées lors de la conversion implicite des types de paramètres. LICENCE LMD 2 eme année - Abdelkader ALEM 115
Polymorphisme q Les conversions explicites de références : La compatibilité est implicite entre référence à un objet d’un type donné et une référence à un objet d’un type ascendant. Dans le sens inverse, la compatibilité n’est pas implicite. Exemple: Class graphique {……. } Class Cercle extends graphique {……. . } …. . graphique g, g 1; Cercle c, c 1; c= new graphique (…. ) ; //Erreur de compilation g= new Cercle (…) //Juste g 1 = new graphique (…. ); //évident c 1= new Cercle(…); //évident c 1 = g 1 //faux (Conversion implicite illégale) g 1= c 1; //juste; (conversion implicite légale) LICENCE LMD 2 eme année - Abdelkader ALEM 116
Polymorphisme q Les conversions explicites de références : Ø Il faut réaliser une conversion explicite c 1 = (Cercle) g 1; Ø Toutefois cette syntaxe qui est acceptée à la compilation peut être refusée à l’exécution et le traitement peut être arrêtée s’ il n ‘y a pas compatibilité effective entre les types. LICENCE LMD 2 eme année - Abdelkader ALEM 117
Polymorphisme q Cas d’une méthode surdéfinie (surchargée): class A {. . . } class B extends A {. . . } class Util { static void f(int p, B b) {. . . } static void f(float x, A a) {. . . } }. . . A a = new A() ; B b = new B() ; int n ; float x ; Util. f(n, b) ; // OK sans conversions : appel de f(int, B) Util. f(x, a) ; // OK sans conversions : appel de f(float, A) Util. f(n, a) ; // conversion de n en float : appel de f(float, A) Util. f(x, b) ; // conversion de b en A : appel de f(float, A) LICENCE LMD 2 eme année - Abdelkader ALEM 118
Polymorphisme q Cas d’une méthode surdéfinie (surchargée): Voici un second exemple, class A {. . . } class B extends A {. . . } class Util { static void f(int p, A a) {. . . } static void f(float x, B b) {. . . } }. . . A a = new A() ; B b = new B() ; int n ; float x ; Util. f(n, a) ; // OK sans conversions : appel de f(int, A) Util. f(x, b) ; // OK sans conversions : appel de f(float, B) Util. f(n, b) ; // erreur compilation car ambigu : deux possibilités : // soit convertir n en float et utiliser f(float, B) // soit convertir b en A et utiliser f(int, A) Util. f(x, a ) ; // erreur compilation : aucune fonction ne convient // (on ne peut pas convertir implicitement de A en B // ni de float en int) LICENCE LMD 2 eme année - Abdelkader ALEM 119
Les classes abstraites Une classe abstraite est une classe qui ne permet pas d’instancier des objets. Elle ne peut servir que de classe de base pour une dérivation. Elle se déclare ainsi : abstract class A {. . . } q Dans une classe abstraite, on peut trouver classiquement des méthodes et des champs, dont héritera toute classe dérivée. Mais on peut aussi trouver des méthodes dites abstraites, c’est-à-dire dont on ne fournit que la signature et le type de la valeur de retour. q Par exemple : q abstract class A { public void f() {. . . } // f est définie dans A public abstract void g(int n) ; // g n’est pas définie dans A ; on n’en // a fourni que l’en-tête } LICENCE LMD 2 eme année - Abdelkader ALEM 120
Les classes abstraites Comme les autres classes (et les interfaces), une classe abstraite définit un nouveau type qui peut être associé à un identificateur (Déclaration de variables, champs, tableaux, . . ). q Comme nous l'avons vu dans un des chapitres précédents, les classes peuvent être considérées comme étant des moules (des modèles, des plans, . . . ) permettant de fabriquer des objets. q Si l'on poursuit avec cette métaphore, les classes abstraites peuvent être considérées comme étant des moules incomplets (des modèles partiels, des plans non terminés, . . . ) qui ne peuvent pas être utilisés tels quels pour créer des objets mais qui peuvent être utilisés pour fabriquer d'autres plans plus précis (représentés par des sous-classes) qui seront complétés et qui permettront, eux, de créer des objets (des instances des sous-classes). q LICENCE LMD 2 eme année - Abdelkader ALEM 121
Les classes abstraites Bien entendu, on pourra déclarer une variable de type A : A a ; // OK : a n’est qu’une référence sur un objet de type A ou dérivé q En revanche, toute instanciation d’un objet de type A sera rejetée par le compilateur : a = new A(. . . ) ; // erreur : pas d’instanciation d’objets d’une classe abstraite q En revanche, si on dérive de A une classe B qui définit la méthode abstraite g : class B extends A { public void g(int n) {. . . } // ici, on définit g. . . } q on pourra alors instancier un objet de type B par new B(. . . ) et même affecter sa référence à une variable de type A : A a = new B(. . . ) ; // OK q LICENCE LMD 2 eme année - Abdelkader ALEM 122
Les classes abstraites q Quelques règles 1. Dès qu’une classe comporte une ou plusieurs méthodes abstraites, elle est abstraite, et ce même si l’on n’indique pas le mot-clé abstract devant sa déclaration (ce qui reste quand même vivement conseillé). Ceci est correct : class A { public abstract void f() ; // OK. . . } Ø Malgré tout, A est considérée comme abstraite et une expression telle que new A(. . . ) sera rejetée LICENCE LMD 2 eme année - Abdelkader ALEM 123
Les classes abstraites q Quelques règles 2. Une méthode abstraite doit obligatoirement être déclarée public, ce qui est logique puisque sa vocation est d’être redéfinie dans une classe dérivée. 3. Dans l’en-tête d’une méthode déclarée abstraite, les noms d’arguments muets doivent figurer (bien qu’ils ne servent à rien) : abstract class A { public abstract void g(int) ; // erreur : nom d’argument (fictif) obligatoire } 4. Une classe dérivée d’une classe abstraite n’est pas obligée de (re)définir toutes les méthodes abstraites de sa classe de base (elle peut même n’en redéfinir aucune). Dans ce cas, elle reste simplement abstraite (il est quant même nécessaire de mentionner abstract dans sa déclaration) : LICENCE LMD 2 eme année - Abdelkader ALEM 124
Les classes abstraites q Quelques règles Exemple: abstract class A { public abstract void f 1() ; public abstract void f 2 (char c) ; . . . } abstract class B extends A // abstract obligatoire ici { public void f 1 () {. . . } // définition de f 1. . . // pas de définition de f 2 } Ø Ici, B définit f 1, mais pas f 2. La classe B reste abstraite (même si on ne l’a pas déclarée ainsi). LICENCE LMD 2 eme année - Abdelkader ALEM 125
Les classes abstraites q Quelques règles 5. Une classe dérivée d’une classe non abstraite peut être déclarée abstraite et/ou contenir des méthodes abstraites. Ø Notez que, toutes les classes dérivant de Object, nous avons utilisé implicitement cette règle dans tous les exemples précédents. 6. Les méthodes déclarées avec l'un des modificateurs suivants : static, private ou final ne peuvent pas être abstraites étant donné qu'elles ne peuvent pas être redéfinies dans une sous-classe. 7. Une classe déclarée final ne peut pas contenir de méthodes abstraites car elle ne peut pas être sous-classée. q Exemple Ø Ø Ø Voici un exemple de programme illustrant l’emploi d’une classe abstraite nommée Affichable, dotée d’une seule méthode abstraite affiche. Deux classes Entier et Flottant dérivent de cette classe. La méthode main utilise un tableau hétérogène d’objets de type Affichable qu’elle remplit en instanciant des objets de type Entier et Flottant. LICENCE LMD 2 eme année - Abdelkader ALEM 126
Les classes abstraites abstract class Affichable { abstract public void affiche() ; } class Entier extends Affichable { public Entier (int n) { valeur = n ; } public void affiche() { System. out. println ("Je suis un entier de valeur " + valeur) ; } private int valeur ; } class Flottant extends Affichable { public Flottant (float x) { valeur = x ; } public void affiche() { System. out. println ("Je suis un flottant de valeur " + valeur) ; } private float valeur ; } LICENCE LMD 2 eme année - Abdelkader ALEM 127
Les classes abstraites abstract class Affichable { abstract public void affiche() ; } class Entier extends Affichable { public Entier (int n) { valeur = n ; } public void affiche() { System. out. println ("Je suis un entier de valeur " + valeur) ; } private int valeur ; } class Flottant extends Affichable { public Flottant (float x) { valeur = x ; } public void affiche() { System. out. println ("Je suis un flottant de valeur " + valeur) ; } private float valeur ; } LICENCE LMD 2 eme année - Abdelkader ALEM 128
Les classes abstraites public class Main { public static void main (String[] args) { Affichable [] tab ; tab = new Affichable [3] ; tab [0] = new Entier (25) ; tab [1] = new Flottant (1. 25 f) ; ; tab [2] = new Entier (42) ; int i ; for (i=0 ; i<3 ; i++) tab[i]. affiche() ; } } Je suis un entier de valeur 25 Je suis un flottant de valeur 1. 25 Je suis un entier de valeur 42 LICENCE LMD 2 eme année - Abdelkader ALEM 129
Les classes abstraite: Exemple q Supposons que nous voulions manipuler deux formes géométriques, rectangle (donné par son point haut, gauche, sa largeur et sa longueur) et cercle (donné par son centre et son rayon). Nous désirons pouvoir déplacer ces formes géométriques, calculer leur surface et leur périmètre. 1. sans classe abstraite 2. Avec classe abstraite LICENCE LMD 2 eme année - Abdelkader ALEM 130
Les classes abstraites: Exemple 1 - class Rectangle{ int x, y, largeur, longueur; Rectangle(int x, int y, int la, int lo) { this. x = x; this. y = y; largeur = la; longueur = lo; } void deplace. De( int dx, int dy){ x+=dx; y+=dy; } double perimetre(){ return 2*(largeur+longueur); } double surface(){ return largeur*longueur; } } class Cercle{ int x, y, rayon; Cercle(int x, int y, int r){ this. x = x; this. y = y; rayon = r; } void deplace. De( int dx, int dy){ x+=dx; y+=dy; } double perimetre(){ return 2*Math. PI*rayon; } double surface(){ return Math. PI*rayon; } } LICENCE LMD 2 eme année - Abdelkader ALEM 131
Les classes abstraites: Exemple 2 - abstract class Forme{ int x, y; Forme(int x, int y){ this. x = x; this. y = y; } void deplace. De( int dx, int dy){ x+=dx; y+=dy; } abstract double perimetre(); abstract double surface(); } class Rectangle extends Forme{ int largeur, longueur; Rectangle(int x, int y, int la, int lo) { super(x, y); largeur = la; longueur = lo; } double perimetre(){ return 2*(largeur+longueur); } double surface(){ return largeur*longueur; } } class Cercle extends Forme{ int rayon; Cercle(int x, int y, int r){ super(x, y); rayon = r; } double perimetre(){ return 2*Math. PI*rayon; } double surface(){ return. Math. PI*rayon; } } LICENCE LMD 2 eme année - Abdelkader ALEM 132
Les classes abstraites q Remarque Une classe abstraite peut ne comporter que des méthodes abstraites et aucun champ. C’est d’ailleurs ce qui se produit ici. Dans ce cas, nous verrons qu’une interface peut jouer le même rôle. q Interface ? ? ? (CHAPITRE SUIVANT) LICENCE LMD 2 eme année - Abdelkader ALEM 133
Chapitre 4: Interfaces et Implémentation LICENCE LMD 2 eme année - Abdelkader ALEM 134
Les Interfaces q Une classe abstraite permettait de définir dans une classe de base des fonctionnalités communes à toutes ses descendantes, tout en leur imposant de redéfinir certaines méthodes. q Si l’on considère une classe abstraite n’implantant aucune méthode et aucun champ (hormis des constantes), on aboutit à la notion d’interface. q En effet, une interface définit les en-têtes d’un certain nombre de méthodes, ainsi que des constantes. q ATTENTION : le terme "interface" n'a rien à voir ici avec les "interfaces graphiques" LICENCE LMD 2 eme année - Abdelkader ALEM 135
Les Interfaces q Cette dernière notion se révèle plus riche qu’un simple cas particulier de classe abstraite. En effet : Ø Une classe pourra implémenter plusieurs interfaces (alors qu’une classe ne pouvait dériver que d’une seule classe abstraite), Ø La notion d’interface va se superposer à celle de dérivation, et non s’y substituer, Ø Les interfaces pourront se dériver, Ø On pourra utiliser des variables de type interface. LICENCE LMD 2 eme année - Abdelkader ALEM 136
Les Interfaces q Définition d’une interface: Comme une classe et une classe q q abstraite, une interface permet de définir un nouveau type (référence). Le comportement des objets de ce type (les opérations que l'on peut effectuer) sera déterminé par le contenu (la définition) de cette interface. Une interface constitue essentiellement une spécification qui laisse de côté les détails d'implémentation. L'interface définit ainsi une sorte de contrat que les classes qui l'implémenteront s'engagent à respecter. La notion d'interface est assez proche de la notion de classe abstraite mais elle comporte cependant un certain nombre de spécificités qui l'en distinguent et qui en étendent le potentiel. LICENCE LMD 2 eme année - Abdelkader ALEM 137
Les Interfaces q Du point de vue syntaxique, la définition d'une interface est proche de celle d'une classe abstraite. Il suffit de remplacer les mots-clés abstract class par le mot-clé interface : public interface Printable { public void print(); } Une fois l'interface déclarée, il est possible de déclarer des variables de ce (nouveau) type : Printable document; Printable[] print. Spool; LICENCE LMD 2 eme année - Abdelkader ALEM 138
Les Interfaces q Le corps d'une interface peut contenir : Ø Des constantes qui sont implicitement publiques. Ø Les modificateurs static et final ne sont pas nécessaires (implicites). Ø Des méthodes abstraites qui sont obligatoirement publiques Le modificateur abstract n'est pas nécessaire (implicite). Ø Le modificateur public n'est pas nécessaire (implicite). Ø Des méthodes avec une implémentation par défaut Le modificateur default doit être utilisé. Ø Des méthodes statiques. q Par contre Une interface Ø ne peut pas définir de champs d'instance. Ø 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). LICENCE LMD 2 eme année - Abdelkader ALEM 139
Utilisation des Interfaces q En Java, une classe ne peut hériter que d'une et d'une seule classe parente (héritage simple). Une classe peut, par contre, implémenter une ou plusieurs interfaces en utilisant la syntaxe suivante : implements interface 1, interface 2, . . . q 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. Exemples : public class Rapport implements Printable {. . . } public class Livreimplements Printable, Zoomable {. . . } public class Circle extends Graphique implements Printable {. . . } public class Cube extends Rectangle implements Printable, Zoomable {} LICENCE LMD 2 eme année - Abdelkader ALEM 140
Utilisation des Interfaces q Lorsqu'une classe déclare une interface dans sa clause implements, elle indique ainsi qu'elle s'engage à fournir une implémentation (c'est-à-dire un corps) pour chacune des méthodes abstraites de cette interface. q Si une classe implémente une interface mais ne fournit pas d'implémentation pour toutes les méthodes abstraites de l'interface, elle hérite des méthodes (abstraites) non implémentées de l'interface et doit elle-même être déclarée abstract. q Si une classe implémente plus d'une interface, elle doit implémenter toutes les méthodes abstraites de chacune des interfaces mentionnées dans la clause implements (ou alors être déclarée abstract). LICENCE LMD 2 eme année - Abdelkader ALEM 141
Utilisation des Interfaces: Exemple // Interface interface Equation. Général { public abstract void résolution(); public void affichage(); } // Classe Equation du second degré dérivée class Equation. Degré 2 implements Equation. Général {. . . public void affichage() { // super. affichage(); System. out. print("Equation polynomiale: "); System. out. println("Equation quadratique"); . . . } } LICENCE LMD 2 eme année - Abdelkader ALEM 142
Utilisation des Interfaces: Exemple // Classe Equation du premier degré class Equation. Degré 1 implements Equation. Général {. . . public void affichage() { // super. affichage(); System. out. print("Equation polynomiale: "); System. out. println("Equation linéaire"); . . . } } public class Test. Equation { public static void main(String[] args) { Equation. Général système[] = new Equation. Général[2]; système[0] = new Equation. Degré 2(1. 0, 5. 0, 1. 0); système[1] = new Equation. Degré 1(1. 0, 5. 0); . . . } } LICENCE LMD 2 eme année - Abdelkader ALEM 143
q q q Variables de type interface et polymorphisme La vocation d’une interface soit d’être implémentée par une classe, on peut définir des variables de type interface : public interface I {. . . }. . . I i ; // i est une référence à un objet d’une classe implémentant l’interface I Bien entendu, on ne pourra pas affecter à i une référence à quelque chose de type I puisqu’on ne peut pas instancier une interface. En revanche, on pourra affecter à i n’importe quelle référence à un objet d’une classe implémentant l’interface I : class A implements I {. . . }. . . I i = new A(. . . ) ; // OK De plus, à travers i, on pourra manipuler des objets de classes quelconques, nonnécessairement liées par héritage, pour peu que ces classes implémentent l’interface I. Voici un exemple illustrant cet aspect. Une interface Affichable comporte une méthode affiche. Deux classes Entier et Flottant implémentent cette interface (aucun lien d’héritagen’apparaît ici). On crée un tableau hétérogène de références de "type" Affichable qu’on remplit en instanciant des objets de type Entier et LICENCE LMD 2 eme année - Abdelkader ALEM 144 Flottant
Variables de type interface et polymorphisme Exemple: interface Affichable { void affiche() ; } class Entier implements Affichable { public Entier (int n) { valeur = n ; } public void affiche() { System. out. println ("Je suis un entier de valeur " + valeur) ; } private int valeur ; } class Flottant implements Affichable { public Flottant (float x) { valeur = x ; } public void affiche() { System. out. println ("Je suis un flottant de valeur " + valeur) ; } private float valeur ; } LICENCE LMD 2 eme année - Abdelkader ALEM 145
Variables de type interface et polymorphisme public class Main { public static void main (String[] args) { Affichable [] tab ; tab = new Affichable [3] ; tab [0] = new Entier (25) ; tab [1] = new Flottant (1. 25 f) ; ; tab [2] = new Entier (42) ; int i ; for (i=0 ; i<3 ; i++) tab[i]. affiche() ; } } ***************************** Je suis un entier de valeur 25 Je suis un flottant de valeur 1. 25 Je suis un entier de valeur 42 LICENCE LMD 2 eme année - Abdelkader ALEM 146
Interface et classe dérivée q La clause implements est une garantie qu’offre une classe d’implémenter les fonctionnalités proposées dans une interface. Elle est totalement indépendante de l’héritage ; autrement dit, une classe dérivée peut implémenter une interface (ou plusieurs) : interface I { void f(int n) ; void g() ; } class A {. . . } class B extends A implements I { // les mméthodes f et g doivent soit être déjà définies dans A, // soit définies dans B } q On peut même rencontrer cette situation : interface I 1 {. . . } interface I 2 {. . . } class A implements I 1 {. . . } class B extends A implements I 2 {. . . } LICENCE LMD 2 eme année - Abdelkader ALEM 147
Interfaces et constantes q L’essentiel du concept d’interface réside dans les en-têtes de méthodes qui y figurent. Mais une interface peut aussi renfermer des constantes symboliques qui seront alors accessibles à toutes les classes implémentant l’interface : interface I { void f(int n) ; void g() ; static final int MAXI = 100 ; } class A implements I { // doit définir f et g // dans toutes les méthodes de A, on a accès au symbole MAXI : // par exemple : if (i < MAXI). . . } LICENCE LMD 2 eme année - Abdelkader ALEM 148
Interfaces et constantes q Mais une interface peut aussi renfermer des constantes symboliques qui seront alors accessibles à toutes les classes implémentant l’interface : interface I { void f(int n) ; void g() ; static final int MAXI = 100 ; } class A implements I { // doit définir f et g // dans toutes les méthodes de A, on a accès au symbole MAXI : // par exemple : if (i < MAXI). . . } q Ces constantes sont automatiquement considérées comme si elles avaient été déclarées static et final. q Il doit s’agir obligatoirement d’expressions constantes. Elles sont accessibles en dehors d’une classe implémentant l’interface. Par exemple, la constante MAXI de l’interface I se notera simplement I. MAXI. LICENCE LMD 2 eme année - Abdelkader ALEM 149
Dérivation d’une interface q On peut définir une interface comme une généralisation d’une autre. On utilise là encore le mot-clé extends, ce qui conduit à parler d’héritage ou de dérivation interface I 1 { void f(int n) ; static final int MAXI = 100 ; Une classe }qui implémente une sous-interface doit implémenterinterface les. I 2 extends méthodes abstraites définies I 1 ; directement{ void parg()l'interface ainsi que les méthodes static final int MINI = 20 ; abstraites héritées de toutes les interfaces parentes de } En fait, la définition de I 2 est totalement équivalente à : la sous-interface I 2 { void f(int n) ; void g() ; static final int MAXI = 100 ; static final int MINI = 20 ; } LICENCE LMD 2 eme année - Abdelkader ALEM 150
Conflits de noms q Considérons : interface I 1 { void f(int n) ; void g() ; } interface I 2 { void f(float x) ; void g() ; } class A implements I 1, I 2 { // A doit définir deux méthodes f : void f(int) et void f(float), // mais une seule méthode g : void g() q En ce qui concerne la méthode g, en revanche, il semble qu’un conflit de noms apparaisse. En fait, il n’en est rien puisque les deux interfaces I 1 et I 2 définissent le même en-tête de méthode g ; il suffit donc que A définisse la méthode requise (même si elle est demandée deux fois !). LICENCE LMD 2 eme année - Abdelkader ALEM 151
Conflits de noms q considérons maintenant : interface I 1 { void f(int n) ; void g() ; } interface I 2 { void f(float x) ; int g() ; } class A implements I 1, I 2 { // pour satisfaire à I 1 et I 2, A devrait contenir à la fois une méthode // void g() et une méthode int g(), ce qui n’est pas possible // d’après les règles de redéfinition } q Cette fois, une classe ne peut implémenter à la fois I 1 et I 2. LICENCE LMD 2 eme année - Abdelkader ALEM 152
Conflits de noms q Résumé: Ø 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 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 en utilisant la notation qualifiée (Interface. Constante) LICENCE LMD 2 eme année - Abdelkader ALEM 153
Exercice: utilisation des interfaces q. Le but de l'exercice est de créer une hiérarchie de classes pour représenter les étudiants d'une université. Il y a 3 types d'étudiants : ceux en Licence, ceux en Master, et ceux en Doctorat. Chaque étudiant a un nom, une adresse et un numéro q. Les étudiants ont un profil. Pour les étudiants en Licence on parle de parcours. Les étudiants en Master une spécialité et les étudiants en Doctorat un directeur de recherche 1. Définir les classes nécessaires à cette hiérarchie de classes, en leurs ajoutant les membres nécessaires et les méthodes usuelles (constructeurs, get()et set() etc. . . ). 2. Écrire une application qui construit un ensemble d'étudiants (utiliser la classe Scanner (Lire) pour que l'utilisateur puisse saisir les données) affiche une liste d'étudiants dans l'ordre selon le numéro § Pour chaque étudiant, il faut afficher toutes les informations le concernant LICENCE LMD 2 eme année - Abdelkader ALEM 154
- Slides: 154