INTERFACE ET POLYMORPHISME 2019-04-17 IFT1020 - A03
OBJECTIFS Apprendre à utiliser les interfaces. Faire des conversions entre références de super- types et de sous-types. Comprendre le concept de polymorphisme. Apprécier les interfaces pour découpler des classes. Apprendre à implanter des classes d’aide (“inner classes”). 2019-04-17 IFT1020 - A03
CODES NonReutilisables Polymorphiques Stratégiques Anonymous Inner 2019-04-17 IFT1020 - A03
Interfaces vs. Classes Toutes les méthodes dans une interface sont abstraites– pas d’implantation. Toutes les méthodes dans une interface sont public. Une inteface n’a pas de variables– seulement des constantes. 2019-04-17 IFT1020 - A03
Réaliser une Interface On indique les interfaces à implanter avec l’énoncé implements. On fournit les définitions des méthodes de l’interface class NomClasse implements Mesurable { public double mesure() { implantation } méthodes et variables additionnelles } La classe doit définir les méthodes public. 2019-04-17 IFT1020 - A03
Diagramme UML : SacDonnees CompteBanque PieceMonnaie (interface) Mesurable SacDonnees Notez que la classe SacDonnees est découplée de CompteBanque et de PieceMonnaie. 2019-04-17 IFT1020 - A03
Symboles des relations UML Relation Symbole Type de ligne Type flèche Héritage Pleine Pleine Réalisation Pointillée Pleine Association Pleine Vide Dépendance Pointillée Vide 2019-04-17 IFT1020 - A03
Définir une interface Exemple: But: public interface NomInterface { spécifications des méthodes } Exemple: public interface Mesurable { double mesure(); } But: Ajouter une interface avec ses spécifications de méthodes. Les méthodes sont automatiquement public. 2019-04-17 IFT1020 - A03
Implanter une interface public class NomClasse implements NomInterface1, NomInterface2, ... { méthodes variables } Example: public class CompteBanque implements Mesurable { // autres méthodes dans CompteBanque public double mesure() { // implantation de la méthode } } But: Définir une nouvelle classe qui satisfait et implante les méthodes de une ou plusieurs interfaces. 2019-04-17 IFT1020 - A03
Conversion de types On peut convertir d’un type de classe à un type d’interface réalisée: CompteBanque compte = new CompteBanque(10000); Mesurable x = compte; // OK Une variable du même type d’interface peut aussi faire référence à une PieceMonnaie x = new PieceMonnaie(0.10); // OK On ne peut cependant pas convertir entre types non reliés x = new Rectangle(5, 10, 20, 30); // ERREUR 2019-04-17 IFT1020 - A03
Casts Ajouter une pièce de monnaie à un sac de données : SacDonnees piecesMonnaie = new SacDonnees(); piecesMonnaie.ajouter(new PieceMonnaie(0.25)); piecesMonnaie.ajouter(new PieceMonnaie(0.10)); ... Obtenir la pièce maximum avec la méthode maximum : Mesurable maximum = piecesMonnaie.maximum(); Qu’est-ce qu’on peut faire avec maximum? Ce n’est pas une PieceMonnaie! String nom = maximum.nom(); // ??? Vous savez que c’est une pièce mais le compilateur non. Dans ce cas, il faut appliquer le cast : PieceMonnaie max = (PieceMonnaie)maximum; String nom = max.nom(); Si vous avez tord et que maximum n’est pas une pièce, le compilateur lance (throws) une exception. ERREUR 2019-04-17 IFT1020 - A03
L’opérateur instanceof… Utilisez instanceof pour des casts sécuritaires: if(maximum instanceof PieceMonnaie) { PieceMonnaie max = (PieceMonnaie)max; . . . } 2019-04-17 IFT1020 - A03
…L’opérateur instanceof objet instanceof NomClasse Example: if(x instanceof PieceMonnaie) { PieceMonnaie c = (PieceMonnaie)x; } But: Retourner true si l’objet est une instance de NomClasse (ou une de ses sous-classes), false autrement. 2019-04-17 IFT1020 - A03
Polymorphisme… Les variables interface contiennent une référence à un objet d’une classe qui réalise l’interface Mesurable x; x = new CompteBanque(10000); x = new PieceMonnaie(0.1); On ne peut pas construire directement une interface! x = new Mesurable(); // ERREUR On peut appeller les méthodes de l’interface: double m = x.mesure(); // OK Ce qui pose la question “quelle méthode est appellée?” 2019-04-17 IFT1020 - A03
…Polymorphisme La méthode dépend de l’objet réel. Si x réfère à un compte de banque, ça appelle CompteBanque.mesure Si x réfère à une pièce de monnaie, ça appelle PieceMonnaie.mesure Le mot polymorphisme vient du grec: plusieurs formes. Le type de l’objet réel, seulement connu à l’exécution, détermine la méthode à appeler. C’est la liaison tardive ou dynamique (late binding). Résolue à l’exécution. ATTENTION : le polymorphisme diffère de la surdéfinition (overloading). La sur-définition est résolue par le compilateur. 2019-04-17 IFT1020 - A03
Interface stratégique Désavantages de l’interface Mesurable: On doit modifier nos classes, ajouter l’interface et les méthodes. On ne peut prendre qu’une seule (sorte de) mesure de nos classes. Remède: passer l’objet-à-mesurer en argument à une méthode: public interface Mesureur { double mesure(Object unObjet); } Object est le “plus petit commun dénominateur" de toutes les classes. 2019-04-17 IFT1020 - A03
Utiliser une Interface stratégique La méthode ajouter demande au mesureur (et non pas à l’objet ajouté) de faire la mesure public void ajouter(Object x) { somme += mesureur.mesure(x); if(nombre == 0 || mesureur.mesure(maximum) < mesureur.mesure(x)) maximum = x; nombre++; } 2019-04-17 IFT1020 - A03
Utiliser une interface stratégique Mesurer la surface d’un rectangle class MesureurRectangle implements Mesureur { public double mesure(Object unObject) { Rectangle unRectangle = (Rectangle)unObject; double surface = unRectangle.getWidth() * unRectangle.getHeight(); return surface; } } On doit faire un cast de Object à Rectangle On passe le mesureur au constructeur du sac de données: Mesureur m = new MesureurRectangle(); SacDonnees donnees = new SacDonnees(m); 2019-04-17 IFT1020 - A03
Diagramme UML : Mesureur MesureurRectangle Rectangle SacDonnees (interface) Mesureur Notez la classe Rectangle découplée de l’interface Mesureur 2019-04-17 IFT1020 - A03
Classes intérieures (inner) Une classe “triviale” peut être définie à l’intérieur d’une méthode public static void main(String[] args) { class MesureurRectangle implements Mesureur { . . . } Mesureur m = new MesureurRectangle(); . . . // La classe MesureurRectangle n’est pas utilisée // plus loin qu’ici. } 2019-04-17 IFT1020 - A03
Classes intérieures (inner)… Déclaration à l’intérieur d’une méthode : class NomClasseExterieure { signature de la méthode { . . . class NomClasseInterieure { méthodes champs } . . . } . . . } 2019-04-17 IFT1020 - A03
…Classes intérieures (inner)… Déclaration à l’intérieur d’une classe : class NomClasseExterieure { méthodes champs spécifications-accès class NomClasseInterieure { méthodes champs } . . . } 2019-04-17 IFT1020 - A03
…Classes intérieures (inner) Exemple: public class Test { public static void main(String[] args) { class MesureurRectangle implements Mesureur { . . . } ... } } But: Définir une classe inner dont les méthodes ont accès aux mêmes variables et méthodes que les méthodes de la classe outer. 2019-04-17 IFT1020 - A03