I21 Algorithmique et programmation II David Gross-Amblard, Joël Savelli IEM-uB GFDL 1.2 CM 4/8 v2
i IEM / uB GFDL Encapsulation Déclaration Instanciation Constructions Accès aux membres et droits d'accès Destruction d'instances Accesseurs : un peu de modélisation Membres de classe
i IEM / uB GFDL 1.23 Membres de classe Où toute la lumière sera faite sur l'affreux « static »
i IEM / uB GFDL 1.24 Membres de classe ● Membres de classe, ou membres statiques ● Indiqués par le mot clé static class Etudiant { public int nbJeton; // attribut public static int nbEtudiant; // attribut de classe public static Etudiant fromString(String s) // méthode {...} // de classe... }
i IEM / uB GFDL 1.25 Attributs de classe / partagés ● Attributs partagés par toutes les instances (Etudiant e1, e2) e1.nbJeton=5; e2.nbJeton=6; e1.nbEtudiant=5; e2.nbEtudiant=6; // modifie précédente valeur nbJeton : 5nbJeton : 6 NbEtudiant : 6 e1 :e2 :
i IEM / uB GFDL 1.26 Membres de classe ● N'ont pas besoin d'instanciation pour être utilisés Etudiant e; // pas de new System.out.println(e.nbEtudiant); System.out.println(e.fromString(''John Doe'')); ● Habituellement, accès par le nom de classe System.out.println(Etudiant.nbEtudiant); System.out.println(Etudiant.fromString(''John Doe''));
i IEM / uB GFDL 1.27 Modélisation ? ● Membres de classes : propriétés et traitements concernant la classe mais pas une instance particulière ● Ex. d'attribut de classe : – Propriété statistique sur l'ensemble des instances (nb total d'instance, moyenne d'un attribut,...) ● Ex. de méthode de classe : – Traitement ne nécessitant pas d'instance particulière
i IEM / uB GFDL 1.28 Ex. : compter les instances class Etudiant { public static int nbEtudiant=0; // initialisation public Etudiant(){ // si création d'une instance... nbEtudiant++; // incrémentation du compteur partagé }
i IEM / uB GFDL 1.29 Ex. : méthodes de classes ● Fabriquer un Etudiant à partir d'un texte descriptif (pas d'instance au début) public static Etudiant fromString(String s) // méthode // de classe String nom=analyseNom(s);... int annee=analyseAnnee(s); return new Etudiant(nom,prenom,jour,mois,annee); }
i IEM / uB GFDL Ex. : relation d'équivalence ● Egalité entre 2 étudiants : pas liée à un étudiant particulier public static boolean equals(Etudiant e1, Etudiant e2){ if ((e1.getNom().equals(e2.getNom()) &&...) return true; return false; }
i IEM / uB GFDL Ex. : relation d'équivalence ● Mais pour le equals non-statique ? ● Utiliser la version statique avec l'objet courant en paramètre public boolean equals(Etudiant e){ return Etudiant.equals(this,e); } ● this : référence à l'objet courant, disponible dans le corps des méthodes (non-statiques)
i IEM / uB GFDL Ex. de membres de classe ● System.out.println(); – System : classe – out : attribut statique de System (de type PrintStream) – println() : méthode (non-statique) de l'objet out ● Math.random(); – Math : classe – random() : méthode statique de Math
i IEM / uB GFDL En conclusion ● Membres de classe : très rares cas d'utilisation ● A partir de maintenant, toute utilisation de static devra être très fortement motivée ! (sinon pan sur les doigts)
i IEM / uB GFDL Mais alors pourquoi...?? ● Java : exécution de la méthode main de votre classe ● Exécuteur : ne fait pas d'instanciation, donc main nécessairement static ● Donc tous les attributs utilisés par main : static ● Donc toutes les méthodes utilisées : static ● Horreur...
i IEM / uB GFDL Bonne pratique class Main { public static void main(String[] arg){ // code pour analyser la ligne de commande arg... MonProgramme p=new MonProgramme(); p.demarrer(); } ● Et c'est tout : tout est dans la classe MonProgramme, sans aucun static
i IEM / uB GFDL Encapsulation Déclaration Instanciation Constructions Accès aux membres et droits d'accès Destruction d'instances Accesseurs : un peu de modélisation Membres de classe
i IEM / uB GFDL II. Programmation par objet 1. Motivation 2. Encapsulation 3. Héritage 4. Initiation à la modélisation
3. Héritage ● Motivation ● Définition ● Surcharge et héritage ● Polymorphisme de classe ● Classe abstraite ● Héritage multiple ● Règles de visibilité
i IEM / uB GFDL Principes de la programmation objet ● Encapsulation : rassembler en un nouveau type la représentation et les traitements d'une notion abstraite – ex. : notion d'étudiant : type Etudiant ● Héritage : matérialiser la relation d'héritage (des représentations, des traitements) entre les notions abstraites – ex. : un etudiant est une personne – le type Etudiant hérite (quoi) du type Personne
i IEM / uB GFDL Motivation ● Un étudiant a un nom, un prénom, une date de naissance, des notes ● Une personne a un nom, prénom, date de naissance ● Concrètement, Etudiant : classe avec accesseurs (compliqués), constructeurs,... ● Nombreuses similitudes entre personne et etudiant (ex. attribut nom, methode setDateNaissance);
i IEM / uB GFDL Copier/coller ● Première approche : – copier/coller les attributs et le code de setDateNaissance dans Personne ● Avantage : – rapide ● Inconvénient : – Si vermine dans setDateNaissance, on l'a copiée – Si amélioration à faire, il faut (penser à) la faire aux deux endroits
i IEM / uB GFDL Héritage ● Deuxième approche : on observe que – Propriétés de Personne : incluses dans Etudiant (nom, prenom,date de naissance) – Traitements de Personne : inclus dans Etudiant (les accesseurs aux précédentes propriétés) – On pose que Etudiant est une sorte de Personne, avec des compléments : notes, etc. ● Avantage – Toute amélioration à Personne sera repercutée sur Etudiant : réutilisation du code
3. Héritage ● Motivation ● Définition ● Surcharge et héritage ● Polymorphisme de classe ● Classe abstraite ● Héritage multiple ● Règles de visibilité
i IEM / uB GFDL Héritage ● La classe Etudiant hérite de Personne ● (Etudiant est une sorte de Personne) ● Personne est la classe-mère / super-classe de Etudiant Etudiant Personne
i IEM / uB GFDL Héritage class Personne { private String nom,prenom; private int jourNaissance, moisNaissance, anneeNaissance; public Personne(String inom, String iprenom, int ijn,int imn,int ian){... } public void afficher(){sopln(prenom+'' ''+nom}; public void setDateNaissance(int ijn,int imn,int ian){ // vérification de la cohérence de la date }
i IEM / uB GFDL Etudiant hérite de Personne Class Etudiant extends Personne { private double notei21,notei22; private boolean aSesNotes; public void setNotes(double i21,double i22){... }
i IEM / uB GFDL Exemple d'accès Personne p=new Personne(''Doe'','John',11,1,1980); p.setDateNaissance(11,2,1980); // défini dans Personne p.setNotes(17.0,15.5); // invalide : pas défini dans Personne (une Personne n'est pas une sorte d'Etudiant)
i IEM / uB GFDL Exemple ● Etudiant e=new Etudiant(''Doe'','John',11,1,1980); // constructeur hérité de Personne ● e.setDateNaissance(11,2,1980); // hérité de Personne ● e.setNotes(17.0,15.5); // valide : défini dans Etudiant
3. Héritage ● Motivation ● Définition ● Surcharge et héritage ● Polymorphisme de classe ● Classe abstraite ● Héritage multiple ● Règles de visibilité
i IEM / uB GFDL Surcharge et héritage ● Personne a une méthode afficher() ● Possibilité de redéfinir afficher() pour Etudiant (remplace/surcharge la méthode héritée) class Etudiant {... public void afficher(){ sopln(getNom()+'' ''+getPrenom()+'', étudie à l'UB''); }
i IEM / uB GFDL Surcharge du constructeur ● notei21,notei22 : pas dans Personne, mais dans Etudiant ● où a lieu l'initialisation de notei21, notei22, aSesNotes ? ● Surcharger le constructeur de Personne dans Etudiant ● Appeler avant le constructeur de Personne (pour initialiser nom, prenom, etc.)
i IEM / uB GFDL Surcharge du constructeur class Etudiant { public Etudiant(String inom,String iprenom,int ijn,int imn,int ian){ super(inom,iprenom,ijn,imn,ian); // appel du constructeur de Personne, super- classe aSesNotes=false; // initialisation attribut propre de Etudiant }... }
3. Héritage ● Motivation ● Définition ● Surcharge et héritage ● Polymorphisme de classe ● Classe abstraite ● Héritage multiple ● Règles de visibilité
i IEM / uB GFDL Typage et héritage ● Comme Etudiant hérite (est une sorte de) Personne, on peut fournir un Etudiant chaque fois qu'une Personne est attendue Personne p; p=new Etudiant( ''Bueller'', ''Ferris'',4,7,1970 ); // valide sopln(p.getNom()); // valide : défini dans Personne sopln(p.getNotei21()); // invalide : p est une Personne, d'après le typage
i IEM / uB GFDL Polymorphisme ● Polymorphisme : une variable peut avoir des types différents à différents moments de l'exécution ● Ex. langages à typage faible, sans déclaration (shell, PHP,...) $toto=''12 est mon nombre''; // déclaration à la volée print $toto + 5 // $toto vue comme int, affiche ● Java : typage fort (déclaration préalable), monomorphique
i IEM / uB GFDL Polymorphisme en Java ● Polymorphisme de classe ● Exemple précédent : variable déclarée de type Personne contenant un Etudiant ● Mieux : Personne[] t=new Personne[2]; t[0]=new Personne(''Jean'',''Saisrien'',1,1,2000); t[1]=new Etudiant(''Anne'','Onyme'',3,5,1980);
i IEM / uB GFDL Polymorphisme de classe ● Tableau a contenu polymorphe ● Cohérence maintenue par héritage ● Impact de la surcharge des méthodes: t[0].afficher(); >Jean Saisrien t[1].afficher(); >Anne Onyme, étudie à l'UB ● Méthode à exécuter connue seulement à l'exécution, pas à la compilation (dépend du type) : liaison dynamique
3. Héritage ● Motivation ● Définition ● Surcharge et héritage ● Polymorphisme de classe ● Classe abstraite ● Héritage multiple ● Règles de visibilité
i IEM / uB GFDL Classe abstraite ● Ex. formaliser la notion d'Etre et de Chat Etudiant Personne Etre Chat
i IEM / uB GFDL Classe abstraite ● Formaliser : ''tout être a une masse'' ● attribut masse dans Etre ● Formaliser : ''tout Etre peut être affiché'' ● garantir que tout descendant de Etre possède une méthode void afficher() ● Définir la méthode dans Etre ● Mais quel corps ? ● Aucun : méthode abstraite
i IEM / uB GFDL Classe abstraite abstract class Etre { public abstract void afficher(); // pas de corps } ● Si une méthode est abstraite, la classe l'est aussi ● Toutes les méthodes d'une classe abstraite ne sont pas nécessairement abstraites
i IEM / uB GFDL Classe abstraite ● Il est invalide d'instancier une classe abstraite Etre e=new Etre(); // invalide ● Toute classe descendante d'une classe abstraite, ne définissant pas une des méthodes abstraite, est abstraite
i IEM / uB GFDL Classe abstraite class Chat extends Etre { public void appelerLeChat(){ secouerSacCroquettes(); } } ● Invalide : – classe non marquée abstraite et méthode afficher() pas définie
i IEM / uB GFDL Classe abstraite abstract class Chat extends Etre { public void appelerLeChat(){ secouerSacCroquettes(); } } ● Valide, mais ne peut être instanciée
i IEM / uB GFDL Classe abstraite class Chat extends Etre { public void appelerLeChat(){ secouerSacCroquettes(); } public void afficher(){ sopln(''Je suis un chat''); } } ● Valide, pouvant être instanciée
3. Héritage ● Motivation ● Définition ● Surcharge et héritage ● Polymorphisme de classe ● Classe abstraite ● Héritage multiple ● Règles de visibilité
i IEM / uB GFDL Héritage multiple ● Modéliser ceci : Camping car VéhiculeHabitation
i IEM / uB GFDL Héritage multiple ● Nombreuses difficultés : – Ambiguité de nommage (attributs ayant même nom dans les 2 classes mères) – Plusieurs constructeurs parents : appel dans quel ordre ? ● Disponible en C++ ● Java : non ● Forme limitée avec les interfaces (pas au programme)
3. Héritage ● Motivation ● Définition ● Surcharge et héritage ● Polymorphisme de classe ● Classe abstraite ● Héritage multiple ● Règles de visibilité
i IEM / uB GFDL Règles de visibilité ● Membre public : accessible depuis n'importe quelle classe ● Membre private : accessible uniquement depuis la classe de définition ● (Membre protected : accessible depuis les classes héritières)