Programmation Orientée Objet Introduction à Java
Transcription
Programmation Orientée Objet Introduction à Java
Programmation Orientée Objet Compléments sur l’héritage Julien Provillard http://www.i3s.unice.fr/~provilla/poo/ [email protected] Programmation orientée objet Objectifs/Plan Classes et méthodes finales Classes internes Classes locales Classes anonymes Interfaces fonctionnelles Lambda expressions 2 CLASSES ET MÉTHODES FINALES 3 Programmation orientée objet Classes finales On veut pouvoir empêcher d’hériter d’une classe Pour préserver la sémantique contre la redéfinition par polymorphisme Pour des raisons de sécurités Pour cela, on déclare une classe finale final class A { … } On ne peut pas hériter d’une classe finale Les classes abstraites ne peuvent être finales (leur but est de servir de classe mère) 4 Programmation orientée objet Méthodes finales On veut pouvoir empêcher la redéfinition de certaines méthodes d’une classe Pour cela, on déclare la méthode finale class Addition { final int calcule(int x, int y) { return x + y; } } On ne peut pas redéfinir une méthode finale On peut hériter d’une classe qui contient des méthodes finales 5 Programmation orientée objet Classes vs méthodes finales Une classe finale n’est pas équivalente à une classe dont toutes les méthodes sont finales On peut toujours hériter d’une classe dont toutes les méthodes sont finales pour lui ajouter de nouveaux membres. 6 Programmation orientée objet Classes utilitaires Une classe utilitaire est une classe Dont toutes les méthodes sont statiques Qui ne peut pas être instanciée Exemple: la classe java.lang.Math Pattern de création final class Addition { // pour empêcher l’héritage private Addition() {} // pour cacher le constructeur par défaut static int addition(int x, int y) { return x + y; } } 7 CLASSES INTERNES 8 Programmation orientée objet Classes internes Définition Dans une classe Dans le corps d’une méthode (classes locales) A la volée dans une affectation ou un passage de paramètre (classes anonymes) A la compilation ClasseEnglobante.class ClassEnglobante$1ClasseInterne.class ClassEnglobante$2.class 9 Programmation orientée objet Exemple Classe interne class Liste { Maillon tete; void add(int v) { tete = this.new Maillon(v, tete); } class Maillon { int contenu; Maillon suivant; Maillon(int contenu, Maillon suivant) { this.contenu = contenu; this.suivant = suivant; } } } 10 Programmation orientée objet Lien avec l’objet englobant La classe interne peut accéder aux membres (champs et méthodes) de l’objet englobant Accès à l’instance de la classe englobante avec <NomDeClasse>.this Création d’une instance d’une classe interne depuis l’extérieur de la classe englobante <Instance de NomDeClasse>.new <Inner>(…); Ex : Liste.Maillon m = l.new Maillon(10, null); • Liste est une classe contenant une classe interne Maillon • l est une instance de la classe Liste 11 Programmation orientée objet Classes internes statiques Classes internes statiques class Liste { Maillon tete; void add(int v) { tete = new Liste.Maillon(v, tete); } static class Maillon { int contenu; Maillon suivant; Maillon(int contenu, Maillon suivant) { this.contenu = contenu; this.suivant = suivant; } } } 12 Programmation orientée objet Lien avec la classe englobante Une classe interne ne peut avoir de membres statiques (sauf constantes) Une classe interne statique peut avoir des membres statiques Création d’une instance d’une classe interne depuis l’extérieur de la classe englobante new <NomDeClasse>.<StaticInner>(…); Ex : Liste.Maillon m = new Liste.Maillon(10, null); • Liste est une classe contenant une classe interne statique Maillon 13 Programmation orientée objet Cacher l’implémentation Classe interne private class Liste { private Maillon tete; void add(int v) { tete = new Liste.Maillon(v, tete); } private static class Maillon { int contenu; Maillon suivant; Maillon(int contenu, Maillon suivant) { this.contenu = contenu; this.suivant = suivant; } } } 14 Programmation orientée objet Classes locales Définies dans un bloc d’instruction N’existent pas en dehors du bloc Utiles pour spécialiser des objets (héritage, implémentation d’interface) sans créer une classe visible (implémentation masquée) Ne peuvent utiliser que des variables locales final 15 Programmation orientée objet Classes locales Exemple static CharSequence convert(char[] t) { class ArrayCharSeq implements CharSequence { char[] t; ArrayCharSeq(char[] t) { this.t = t; } public int length() { return t.length; } public char charAt(int i) { return t[i]; } public CharSequence subSequence(int i, int j) { return new ArrayCharSeq(Arrays.copyOfRange(t, i, j)); } public String toString() { return new String(t); } } return new ArrayCharSeq(Arrays.copyOf(t, t.length)); } 16 Programmation orientée objet Opérations binaires OperationBinaire.java interface OperationBinaire { double calcule(double c1, double c2); } Addition.java class Addition implements OperationBinaire { public double calcule(double c1, double c2) { return c1 + c2; } } 17 Programmation orientée objet Calculatrice Calculatrice.java class Calculatrice { private double accumulateur; private OperationBinaire addition = new Addition(); private void applique(OperationBinaire op, double v) { accumulateur = op.calcule(accumulateur, v); } void add(double x) { applique(addition, x); } } Doit-on réellement définir la classe Addition? Instanciation unique 18 Programmation orientée objet Classes anonymes Calculatrice.java class Calculatrice { private double accumulateur; private OperationBinaire addition = new OperationBinaire() { public double calcule(double c1, double c2) { return c1 + c2; } }; private void applique(OperationBinaire op, double v) { accumulateur = op.calcule(accumulateur, v); } void add(double x) { applique(addition, x); } } 19 Programmation orientée objet Classes anonymes Une classe sans nom définie par new <NomClasse>(…) { … } ou new <NomInterface>() { … } Spécialise n’importe quelle classe, interface ou classe abstraite Une classe anonyme ne peut pas avoir de constructeur ! Ne peuvent utiliser que des variables locales final Point getP(double x, double y) { return new Point(x, y) { public String toString { return "Point anonyme (" + x + "," + y + ")"; } }; } 20 Programmation orientée objet Interface fonctionnelle (JDK 8.0) Une interface est dite fonctionnelle si elle ne contient qu’une seule méthode abstraite OperationBinaire est une interface fonctionnelle interface OperationBinaire { double calcule(double c1, double c2); } 21 Programmation orientée objet Interface fonctionnelle (JDK 8.0) Une interface fonctionnelle peut contenir plusieurs méthodes si elles ont des implémentations par défaut OperationBinaire est une interface fonctionnelle interface OperationBinaire { double calcule(double c1, double c2); default double iter(double acc, double... args) { for (double arg : args) acc = calcule(acc, arg); return acc; } } 22 Programmation orientée objet Lambda expressions (JDK 8.0) Une interface fonctionnelle peut être implémenter de manière anonyme par une lambda expression Syntaxe arg -> expression (arg1, arg2, ..., argn) -> expression (arg1, arg2, ..., argn) -> { ... // instructions return ...; } Type des arguments optionnel (inférence de type) (x, y) -> x + y (int x, int y) -> { return x + y; } Suivent exactement les mêmes règles que les classes anonymes 23 Programmation orientée objet Lambda expressions (JDK 8.0) Calculatrice.java class Calculatrice { private double accumulateur; private OperationBinaire addition = (c1, c2) -> c1 + c2; private void applique(OperationBinaire op, double v) { accumulateur = op.calcule(accumulateur, v); } void add(double x) { applique(addition, x); } } 24 Programmation orientée objet Références sur méthodes (JDK 8.0) On peut définir une opération binaire de la manière suivante : OperationBinaire op = (c1, c2) -> Math.max(c1, c2); En fait, on applique la méthode statique max de la classe Math. Peut-on l’exprimer de manière plus directe? Oui! OperationBinaire op = Math::max; Math::max est une référence sur la méthode max de la classe Math et est équivalente à une lambda-expression. 25 Programmation orientée objet Références sur méthodes (JDK 8.0) On peut référencer différents type de méthode et même des constructeurs. Type de méthode Syntaxe Exemple Equivalence Méthodes statiques <class>::<staticMethod> Méthode d’instance d’un objet <object>::<instanceMethod> "toto"::compareTo x -> "toto".compareTo(x) Méthode d’instance d’une classe <class>::<instanceMethod> String::compareTo (x, y) -> x.compareTo(y) Constructeur <class>::new StringBuilder::new () -> new StringBuilder() Math::max (x, y) -> Math.max(x, y) 26