I21 Algorithmique et programmation II David Gross-Amblard, Joël Savelli IEM-uB GFDL 1.2 CM 5/8 v2
i21 IEM-UB GFDL II. Programmation par objet 1. Motivation 2. Encapsulation 3. Héritage 4. Initiation à la modélisation
i21 IEM-UB GFDL Remarques ● Toute classe hérite (implicitement) de la classe Object class Object { public String toString(){ // par défaut, affiche adresse mémoire } public boolean equals(Object O){ // par défaut, compare les adresses mémoires }
i21 IEM-UB GFDL II. Programmation par objet 1. Motivation 2. Encapsulation 3. Héritage 4. Initiation à la modélisation
i21 IEM-UB GFDL Modélisation ● Objectif : passer du problème au code ● Nombreuses méthodologies – MERISE (Tardieu et al., 1983) - RACINES - NIAM - OMT (Object Modeling Technique) - Booch- OOSE- SADT -SART – SA/SD – MACAO -FAST- APTE Unified Process / UML – IDM -...
i21 IEM-UB GFDL Démarche simplifiée ● Étant donné un problème posé (expression des besoins, ex. votre projet) 1.Formaliser ces besoins : cahier des charges 2.Identifier : Les concepts importants : classes leurs opérations : méthodes 3.Identifier les relations entre classes : composition/héritage
i21 IEM-UB GFDL Exemple : Université ● Expression des besoins « Votre programme doit permettre de saisir des étudiants et des enseignants, de désigner un jury de 3 personnes,composé de 2 enseignants et un étudiant. Un enseignant a un bureau. Un étudiant possède des notes. Chaque personne a un nom, un prénom et une date de naissance»
i21 IEM-UB GFDL Cahier des charges ● Données – Personne – Etudiant – Enseignant – Etudiants – Enseignants – Jury ● Opérations – Mise à jour – Ajout / suppression – Constitution
i21 IEM-UB GFDL Classes et méthodes ● Etudiant – nom – prénom – date naissance – notes ● Enseignant – nom – prénom – date naissance – bureau ● parties communes : suggère une super-classe commune ● Personne – nom – prénom – date naissance ● Jury – Etudiant – Ens1 – Ens2
i21 IEM-UB GFDL Relations entre classes ● Identifier les 2 relations suivantes : – composition : est-composé-de – héritage : est-une-sorte-de ● ex. Etudiant est-une-sorte-de Personne ● ex. Jury est-constitué-de Etudiant ● ex. Jury est-constitué-de Enseignant
i21 IEM-UB GFDL est-une-sorte-de / est-composé-de ● A est-une-sorte-de B : relation d'héritage – A hérite de B – class A extends B ● A est-composé-de B : relation de composition – A possède un attribut de type B (ou B[] si plusieurs) class A { B b; // ou B[] b si plusieurs }
i21 IEM-UB GFDL Outils de réflexion et communication ● Aspects statiques du programme – Diagramme d'héritage – Diagramme de composition ● Aspects dynamiques – Diagramme des traitements
i21 IEM-UB GFDL Outil 1 : diagramme d'héritage Etudiant Personne Enseignant : relation d'héritage Jury
i21 IEM-UB GFDL outil 2 : diagramme de composition Etudiant Jury Enseignant : relation de composition
i21 IEM-UB GFDL Méthodes Principe de délégation (subsidiarité) Un objet composite (groupe d’objets) doit déléguer à ses composants tout ce qu’ils peuvent faire seuls Il doit conserver toutes les propriétés et les méthodes qui concernent plusieurs de ses composants
i21 IEM-UB GFDL Principe de délégation class Jury { Enseignant ens1,ens2; Etudiant etu; public void affiche(){ System.out.println("Constitution du jury :"); System.out.println(etu.getNom()+''+etu.getPrenom()); System.out.println(ens1.getNom(+''+ens1.getPrenom()); System.out.println(ens2.getNom(+''+ens2.getPrenom()); }
i21 IEM-UB GFDL Principe de délégation class Jury { Enseignant ens1,ens2; Etudiant etu; public void affiche(){ System.out.println("Constitution du jury :"); etu.affiche(); ens1.affiche(); ens2.affiche(); } Mieux : Etudiant, Enseignant fournissent leur propre affichage
i21 IEM-UB GFDL Outil 3 : diagramme des traitements traitement événement ou donnée cas 1 cas2 événement ou donnée
i21 IEM-UB GFDL Outil 3 : diagramme des traitements Interface graphique validation saisie saisie info. étudiant stockage (Etudiants) objet Etudiant valide boite de dialogue d'erreur invalide
i21 IEM-UB GFDL II. Programmation par objet 1. Motivation 2. Encapsulation 3. Héritage 4. Initiation à la modélisation
i21 IEM-UB GFDL Plan du cours I.Rappels sur Java - types, instructions, procédures, fonctions... I.Programmation par objet - classe, composition, héritage, initiation à la modélisation Bonus I.Types de données et algorithmes - listes, piles, files, arbres, algorithmes de tri, algorithmes récursifs
i21 IEM-UB GFDL Bonus 1. Modularité en Java 2. Mécanisme des exceptions
i21 IEM-UB GFDL Modularité en Java ● Premier niveau : classe – rassemble dans un type sa représentation (attributs) et ses traitements (méthodes) – droits d'accès : gestion de la visibilité (seul le concepteur de la classe connais les détails internes) ● Second niveau : bibliothèques (packages) – rassemble les classes traitant d'un même thème – (ex. tout ce qui est graphique / tout ce qui est Université...) – logiciel industriel : plusieurs centaines de classes
i21 IEM-UB GFDL Bibliothèques ● Pour être dans une même bibliothèque Universite, un ensemble de fichiers de classe : – doivent se trouver dans un même répertoire Universite – doivent commencer par package Universite; ● Classes sans indication de bibliothèque : bibliothèque par défaut (default package)
i21 IEM-UB GFDL Utilisation de bibliothèque ● Clause import import javax.swing.JFrame; // classe JFrame, fenêtre graphique import javax.swing.*; // toutes les classes graphiques ● Par défaut : java.lang.* (permet d'utiliser System, Math, String par exemple)
i21 IEM-UB GFDL Bibliothèques : visibilité package Universite; public class Etudiant {...} private class Enseignant {... } ● Les classes d'une même bibliothèque se voient entre elles ● les classes publiques : visibles par les classes extérieures après import ● les classes private sont invisibles (cachent un détail d'implémentation, inutile pour les autres programmeurs)
i21 IEM-UB GFDL Premier programme enfin clair package tp2; import java.lang.*; public class toto { public static void main(String arg[]){ int x=Lire.d(); // il faut package tp2; au début de // Lire.java System.out.println(Math.floor(12.2));... }
i21 IEM-UB GFDL Bonus 1. Modularité en Java 2. Mécanisme des exceptions
i21 IEM-UB GFDL Les exceptions ● Ex. trouver l'indice de la première occurrence d'un entier dans un tableau public int indice(int recherche,int[] tab){ for(int i=0 ; i<tab.length ; i++) if (tab[i]==recherche) return i; return -1; }
i21 IEM-UB GFDL Motivation ● -1 : valeur spéciale ● Utilisation if (indice(3,tableau)==-1) Sopln(« Pas trouvé »); else position=indice(3,tableau)+2; ● Mauvaise utilisation : position=indice(3,tableau)+2; ● Risque d'erreur, pas détecté à la compilation
i21 IEM-UB GFDL Les exceptions ● Mécanisme permettant – à une méthode de signaler à la méthode appelante qu'un événement exceptionnel est survenu – à la méthode appelante de détecter les événements exceptionnels et d'y réagir selon leur type ● Exception : instance de la classe Exception ● Indication : clause throws ● Signaler : instruction throw ● Adapter : bloc try / catch / finally
i21 IEM-UB GFDL Utilisation public int indice(int rech,int[] tab) throws Exception { for(int i=0;i<tab.length;i++) if (tab[i]==rech) return i; throw new Exception(); }
i21 IEM-UB GFDL Utilisation par l'appelant try { position=indice(3,tableau)+2; catch (Exception e){ System.out.println(« Pas trouvé »); e.printStackTrace(); // affiche l'origine du problème } ● Utiliser indice sans bloc try/catch filtrant le type Exception est invalide (erreur à la compilation) ● catch n'interrompt pas l'exécution
i21 IEM-UB GFDL Définir ses propres exceptions ● Hériter de Exception class PasTrouve extends Exception {} ● Utilisation public int indice(int recherche,int[] tab) throws PasTrouve{ for(int i=0;i<tab.length;i++) if (tab[i]==recherche) return i; throw new PasTrouve(); }
i21 IEM-UB GFDL Utilisation par l'appellant try { position=indice(3,tableau)+2; catch (PasTrouve e){ System.out.println(« Pas trouvé »); e.printStackTrace(); }
i21 IEM-UB GFDL Exceptions prédéfinies ● IOException : erreur d'entrée-sortie (fichier,...) ● ArrayIndexOutOfBoundsException : erreur d'indice dans un tableau ● NullPointerException : accès aux éléments d'un tableau ou aux membres d'un objet dont la référence est à null ● (voir aussi Lire.java)
i21 IEM-UB GFDL Filtrage des différentes exceptions try {... } catch (IOException e){ // traitement de l'IOException } catch(NullPointerException e2){ // traitement du NullPointerException }
i21 IEM-UB GFDL Transmission des exceptions à l'appelant méthode a() void méthode b() throws E2 void c() throws E1,E2 void d() throws E1,E2 class E1 extends Exception {} class E2 extends Exception {}
i21 IEM-UB GFDL Transmission des exceptions à l'appelant méthode a() void méthode b() throws E2 void c() throws E2 void d() throws E1,E2 class E1 extends Exception {} class E2 extends Exception {} catch E1 {...}
i21 IEM-UB GFDL Transmission des exceptions à l'appelant méthode a() void méthode b() void c() throws E2 void d() throws E1,E2 class E1 extends Exception {} class E2 extends Exception {} catch E1 {...} catch E2 {...}
i21 IEM-UB GFDL Transmission des exceptions à l'appelant méthode main() void méthode b() void c() throws E2 void d() throws E1,E2 class E1 extends Exception {} class E2 extends Exception {} catch E1 {...} catch E2 {...} transmission NullPointerException : arrêt du programme
i21 IEM-UB GFDL Programme stable class Main { public static void main(String arg[]){ try { laSuite(); catch (Throwable e){ Sopln(« un problème est survenu : contactez votre revendeur»); sauvegarde(); }
i21 IEM-UB GFDL Clause finally try {... } catch (type1 e1){...} catch(type2 e2){...} finally { // exécuté dans tous les cas, même si aucune exception levée }
i21 IEM-UB GFDL Plan du cours I.Rappels sur Java - types, instructions, procédures, fonctions... I.Programmation par objet - classe, composition, héritage, initiation à la modélisation Bonus I.Types de données et algorithmes - listes, piles, files, arbres, algorithmes de tri, algorithmes récursifs
i21 IEM-UB GFDL Types de données et algorithmes 1.Récursivité 2.Algorithmes de tri 3.Types de données
i21 IEM-UB GFDL Récursivité ● Déclaration récursive : la déclaration d'un notion est dite récursive si cette déclaration contient la notion elle-même ● Notion : procédure, fonction, type,...
i21 IEM-UB GFDL (Type récursif) ● Définition : un type est récursif si sa définition contient un attribut de ce type class RameDeMetro { int nbPlaceAssises; RameDeMetro suiteDeLaRame; } ● (exemples plus tard...)
i21 IEM-UB GFDL Méthodes récursives ● Définition : une méthode est récursive si sa déclaration contient (in fine) un appel à la méthode int factorielle(int n){ if (n==0) return 1; else return n*factorielle(n-1); }
i21 IEM-UB GFDL Méthodes récursives ● Récursivité directe : appel dans la définition de la méthode ● Récursivité indirecte : appel à la méthode réalisé par une autre méthode appelée dans la définition void f(int i){ if (i>0) g(i-1); } void g(int i){ if (i>0) f(i- 1); }
i21 IEM-UB GFDL Terminaison des méthodes récursives ● Comme toute méthode, l'exécution peut ne pas terminer void f(int i){ if (i==0) return 1; elsereturn 2*f(i+1); } ● f(1) appelle f(2) qui appelle f(3)...
i21 IEM-UB GFDL Terminaison des méthodes récursives ● Forme simple : – paramètre n, entier positif ou nul – embranchement en fonction de n ● cas de base (n=0) : pas d'appel récursif ● cas général (n>0) : appels récursifs, pour paramètre strictement inférieures de n void f(int n){ if(n==0) // cas de base if (n>1) // cas général f(n-1) }
i21 IEM-UB GFDL Terminaison ● Critère de terminaison : Il existe une quantité de contrôle entière et positive qui décroît strictement à chaque appel récursif ● Termine, car atteint nécessairement 0 (cas de base) ● (Il n'existe pas de suite infinie strictement décroissante sur les entiers positifs)
i21 IEM-UB GFDL Terminaison des méthodes récursives ● Pas toujours si simple... ● Fonction d'Ackermann-Péter [1926] int ack(int x,int y){ if (x==0) return 2*x; if (y==0) return 1; return ack(x-1,ack(x,y-1)); } ● Termine toujours Wilhelm Ackermann ( )
i21 IEM-UB GFDL Cas particulier : suites définies par récurrence ● suite définie par récurrence, indice n : – (un nombre fini de) cas de bases – cas général : défini en fonction de n'<n ● Ex. factorielle – u 0 =1 – u n =n*u n-1, pour n>0
i21 IEM-UB GFDL Suite par récurrence / fonction récursive ● Suite par récurrence : – u 0 =c 0, u 1 =c 1,...u k =c k – u n =f(u n-1,u n-2,...), n>k ● Fonction récursive correspondante void u(int n){ if (n==0) return c 0... if (n==k) return c k if (n>k) return f(u(n-1),u(n-2),...) }
i21 IEM-UB GFDL Suite par récurrence / fonction récursive ● Toute suite par récurrence peut être transcrite en une fonction récursive ● Il existe des fonctions récursives qui n'ont pas de définition par récurrence – Fonction d'Ackermann (premier exemple 1926, même avec imbrication de suite par récurrence)
i21 IEM-UB GFDL Programmation récursive Avantages ‣ Concision des algorithmes ‣ Analyse plus "naturelle" de certains problèmes Inconvénients ‣ L'exécution demande plus de place mémoire et plus de temps à cause de la répétition des appels (taille de la pile d'appel)
i21 IEM-UB GFDL Version itérative ● Procédure/fonction itérative : sans appel récursif ● On peut toujours transformer une fonction récursive en une version itérative – (méthode générale : simuler la pile des appels) – cas simple : fonctions récursives terminales
i21 IEM-UB GFDL Fonctions récursives terminales ● Une fonction récursive f est dite récursive terminale si il n'y a aucun traitement à effectuer après chaque appel récursif ● Autrement dit : chaque appel récursif de la forme return f(..)
i21 IEM-UB GFDL Exemple : non terminal int factorielle(int n){ if (n>0) return n*factorielle(n-1); else // n==0 return 1; } ● termine toujours, mais non terminale
i21 IEM-UB GFDL Exemple : terminal int factorielle(int n){ return fact(n,1); } int fact(int n,int a){ if (n<=1) return a; else return fact(n-1,n*a); } ● a : accumulateur du résultat
i21 IEM-UB GFDL De récursif terminal à itératif int fact(int n,int a){ if (n<=1) return a; else return fact(n-1,n*a); } int factIteratif(int n, int a){ while(n>1){ a=n*a; n=n-1; } return a; }
i21 IEM-UB GFDL Schéma général fonction f(x){ if (C(x)){ I1(x); return f(T(x)); } else { I2(x); return R(x); }} int f(int x){ while (C(x)){ I1(x); x=T(x); } I2(x); return R(x); }
i21 IEM-UB GFDL Intérêt ● Pas de pile d'appel : moins de mémoire ● Certains compilateurs : détection automatique du récursif terminal ● Récriture automatique du code en conséquence