Programmation Orientée Objet Les classes Julien Provillard http://www.i3s.unice.fr/~provilla/poo/ [email protected] Programmation orientée objet Plan Méthode d’instance ou méthode de classe static final Constructeurs Types énumérés Les modificateurs Expressions booléennes et égalité 2014-2015 J. Provillard - POO 2 Programmation orientée objet Calculatrice Calculatrice.java class Calculatrice { double add(double v1, double v2) { return v1 + v2; } double mul(double v1, double v2) { return v1 * v2; } double inv(double v) { return 1 / v; } } Usage: État : ? Calculatrice c = new Calculatrice(); c.add(12, 5); 3 Programmation orientée objet Méthodes de classes : mot clé static Calculatrice.java class Calculatrice { static double add(double v1, double v2) { return v1 + v2; } static double mul(double v1, double v2) { return v1 * v2; } static double inv(double v) { return 1 / v; } } Usage: État : NON Calculatrice.add(12, 5); 4 Programmation orientée objet Champs de classes : mot clé static Calculatrice.java class Calculatrice { static double add(double v1, double v2) { return v1 + v2; } static double mul(double v1, double v2) { return v1 * v2; } static double inv(double v) { return 1 / v; } État : NON static double PI = 3.14159; } Usage: Calculatrice.add(12, 5); Calculatrice.mul(Calculatrice.PI, 2); 5 Programmation orientée objet Champs constants : mot clé final Calculatrice.java class Calculatrice { static double add(double return v1 + v2; } static double mul(double return v1 * v2; } static double inv(double return 1 / v; } static final double PI = } v1, double v2) { v1, double v2) { v) { 3.14159; Usage: État : NON Calculatrice.add(12, 5); Calculatrice.mul(Calculatrice.PI, 2); 6 Programmation orientée objet Champs constants : mot clé final Le mot clé final impose que la variable ne puisse changer de valeur, elle ne peut qu’être initialisée. L’initialisation ne se fait pas obligatoirement au moment de la déclaration. final int i; int j = 2; j *= 3; i = j; // valide, initialisation de la variable Un champ qui est à la fois static et final correspond à une vraie constante et doit être initialisé à la déclaration. 7 Programmation orientée objet Champs constants : mot clé final Calculatrice.java class Calculatrice { static double add(double return v1 + v2; } static double mul(double return v1 * v2; } static double inv(double return 1 / v; } static final double PI = } v1, double v2) { v1, double v2) { v) { 3.14159; Usage: État : NON Accumulateur ? Mémoire ? Calculatrice.add(12, 5); Calculatrice.mul(Calculatrice.PI, 2); 8 Programmation orientée objet Méthodes d’instance et état Calculatrice.java class Calculatrice { double accumulateur; void add(double v) { accumulateur += v; } void mul(double v) { accumulateur *= v; } double inv() { accumulateur = 1 / accumulateur; État : OUI } static final double PI = 3.1415; } Usage: Calculatrice c = new Calculatrice(); c.add(12); c.mul(Calculatrice.PI); 9 Programmation orientée objet Plan Méthode d’instance ou méthode de classe Constructeurs Initialisation des champs Surcharge du constructeur Surcharge des paramètres Mots clés this. et this( Constructeur par défaut Types énumérés Les modificateurs Expressions booléennes et égalité 10 Programmation orientée objet Initialisation par défaut class Complexe { double reelle, imaginaire; // valeur initiale ? double norme() { return reelle * reelle + imaginaire * imaginaire; } } Initialisation par défaut des champs Valeurs numériques (byte, Booléens (boolean) : false Références : null short, int, long, float, double) : 0 Usage Complexe c1 = new Complexe(); 11 Programmation orientée objet Constructeur class Complexe { double reelle, imaginaire; // valeur initiale ? Complexe(double re, double im) { // constructeur reelle = re; imaginaire = im; } } Initialisation explicite des champs Lorsqu’il n’y a pas de « bonne » valeur par défaut Lorsque l’initialisation nécessite un calcul Usage Complexe c1 = new Complexe(0, 1); 12 Programmation orientée objet Mot clé this. class Complexe { double reelle, imaginaire; // valeur initiale ? Complexe(double reelle, double imaginaire) { this.reelle = reelle; this.imaginaire = imaginaire; } } Surcharge des variables Lorsque le même nom désigne plusieurs variables différentes De manière générale, this désigne l’objet courant. Usage Complexe c1 = new Complexe(0, 1); 13 Programmation orientée objet Constructeur : surcharge class Complexe { double reelle, imaginaire; // valeur initiale ? Complexe(double re, double im) { reelle = re; imaginaire = im; } Complexe(double re) { reelle = re; imaginaire = 0.0; } } Usage Complexe c1 = new Complexe(0, 1); Complexe c2 = new Complexe(6.5); 14 Programmation orientée objet Constructeur : this() class Complexe { double reelle, imaginaire; // valeur initiale ? Complexe(double re, double im) { reelle = re; imaginaire = im; } Complexe(double re) { this(re, 0.0); } } Usage Complexe c1 = new Complexe(0, 1); Complexe c2 = new Complexe(6.5); Complexe c3 = new Complexe(); 15 Programmation orientée objet Instantiation et constructeur Si un ou plusieurs constructeurs explicites Il faut obligatoirement utiliser un de ces constructeurs • • • Complexe c1 = new Complexe(0, 1); Complexe c2 = new Complexe(5); Complexe c3 = new Complexe(); // interdit Le choix du constructeur dépend Du nombre de paramètres effectifs De leur type 16 Programmation orientée objet Constructeur par défaut Si un ou plusieurs constructeurs explicites Il faut obligatoirement utiliser un de ces constructeurs • • • Complexe c1 = new Complexe(0, 1); Complexe c2 = new Complexe(5); Complexe c3 = new Complexe(); // interdit Si aucun constructeur n’est défini Un constructeur « par défaut » est créé automatiquement Il n’a pas de paramètre class Complexe{ double re, im; } Complexe c = new Complexe(); 17 Programmation orientée objet Plan Méthode d’instance ou méthode de classe Constructeurs Types énumérés Les modificateurs Expressions booléennes et égalité 18 Programmation orientée objet Types énumérés Introduits par le JDK 5.0 Les types énumérés ressemblent à des classes Leurs valeurs ressemblent à des champs statiques Le compilateur construit des helpers (constructeurs, affichage, …) Peut avoir des constructeurs, méthodes et champs Exemple [Couleur.java] enum Couleur { TREFLE, CARREAU, CŒUR, PIQUE; } [Test.java] class Test { static public void main(String[] args) { Couleur c = Couleur.TREFLE; Valeur v = Valeur.AS; System.out.println(v + " " + c); } } [Valeur.java] enum Valeur { SEPT, HUIT, NEUF, DIX, VALET, DAME, ROI, AS; } > java Test AS TREFLE 19 Programmation orientée objet Couleur de cartes Sans les énumérés [Couleur.java] class Couleur { int valeur; Couleur(int v) { this.valeur = v; } static final Couleur static final Couleur static final Couleur static final Couleur } TREFLE = new Couleur(1); PIQUE = new Couleur(2); CŒUR = new Couleur(3); CARREAU = new Couleur(4); [Test.java] class Test { static public void main(String[] args) { Couleur c = Couleur.TREFLE; System.out.println(c); } } 20 Programmation orientée objet Couleur de cartes Sans les énumérés [Couleur.java] class Couleur { int valeur; Couleur(int v) { this.valeur = v; } static final Couleur TREFLE = new Couleur(1), PIQUE = new Couleur(2), CŒUR = new Couleur(3), CARREAU = new Couleur(4); } [Test.java] class Test { static public void main(String[] args) { Couleur c = Couleur.TREFLE; System.out.println(c); } } > java Test Couleur@740355a4 21 Programmation orientée objet Couleur de cartes class Couleur { // [Couleur.java] int valeur; Couleur(int v) { this.valeur = v; } static final Couleur TREFLE = new Couleur(1), PIQUE = new Couleur(2), CŒUR = new Couleur(3), CARREAU = new Couleur(4); String nom() { if (valeur == 1) return if (valeur == 2) return if (valeur == 3) return if (valeur == 4) return return "Erreur!"; } "Trèfle"; "Pique"; "Coeur"; "Carreau"; } System.out.println(Couleur.TREFLE.nom()); > java Test Trèfle 22 Programmation orientée objet Méthode toString() class Couleur { // [Couleur.java] int valeur; Couleur(int v) { this.valeur = v; } static final Couleur TREFLE = new Couleur(1), PIQUE = new Couleur(2), CŒUR = new Couleur(3), CARREAU = new Couleur(4); public String toString() { if (valeur == 1) return "Trèfle"; if (valeur == 2) return "Pique"; if (valeur == 3) return "Coeur"; if (valeur == 4) return "Carreau"; return "Erreur!"; } } System.out.println(Couleur.TREFLE); > java Test Trèfle 23 Programmation orientée objet Méthode toString() class Couleur { // [Couleur.java] int valeur; Couleur(int v) { this.valeur = v; } static final Couleur TREFLE = new Couleur(1), PIQUE = new Couleur(2), CŒUR = new Couleur(3), CARREAU = new Couleur(4); public String toString() { switch (valeur) { case 1: return "Trèfle"; case 2: return "Pique"; case 3: return "Coeur"; case 4: return "Carreau"; default: return "Erreur!"; } Ici, on n’a pas besoin d’instruction break car return interrompt immédiatement la méthode en renvoyant la valeur. } 24 Programmation orientée objet Simplification: utilisation d’un constructeur class Couleur { // [Couleur.java] String nom; Couleur(String nom) { this.nom = nom; } static final Couleur TREFLE = new Couleur("Trèfle"), PIQUE = new Couleur("Pique"), CŒUR = new Couleur("Coeur"), CARREAU = new Couleur("Carreau"); public String toString() { return nom; } } 25 Programmation orientée objet switch/case class Valeur { // [Valeur.java] int valeur; Valeur(int v) { valeur = v; } static final Valeur SEPT = new Valeur(7), HUIT = new Valeur(8), NEUF = new Valeur(9), DIX = new Valeur(10), VALET = new Valeur(11), DAME = new Valeur(12), ROI = new Valeur(13), AS = new Valeur(14); public String toString() { switch (valeur) { case 7: case 8: case 9: case 10: return valeur + ""; case 11: return "Valet"; case 12: return "Dame"; case 13: return "Roi"; case 14: return "As"; default: return "Erreur!"; } } } 26 Programmation orientée objet switch/case class Valeur { // [Valeur.java] int valeur; Valeur(int v) { valeur = v; } static final Valeur SEPT = new Valeur(7), HUIT = new Valeur(8), NEUF = new Valeur(9), DIX = new Valeur(10), VALET = new Valeur(11), DAME = new Valeur(12), ROI = new Valeur(13), AS = new Valeur(14); int maValeur() { int v = 0; switch (valeur) { case 11: case 12: case 13: v = valeur – 9; case 14: v = valeur – 3; default: } return v; } } 27 Programmation orientée objet switch/case class Valeur { // [Valeur.java] int valeur; Valeur(int v) { valeur = v; } static final Valeur SEPT = new Valeur(7), HUIT = new Valeur(8), NEUF = new Valeur(9), DIX = new Valeur(10), VALET = new Valeur(11), DAME = new Valeur(12), ROI = new Valeur(13), AS = new Valeur(14); int maValeur() { int v = 0; switch (valeur) { case 11: case 12: case 13: v = valeur – 9; break; case 14: v = valeur – 3; break; default: } return v; } } 28 Programmation orientée objet Rappels : constructeurs class Valeur { // [Valeur.java] int ordre; String nom; Valeur(int o) { this(o, o + ""); } Valeur(int o, String nom) { ordre = o; this.nom = nom; } static final Valeur SEPT = new Valeur(7), HUIT = new Valeur(8), NEUF = new Valeur(9), DIX = new Valeur(10), VALET = new Valeur(11, "Valet"), DAME = new Valeur(12, "Dame"), ROI = new Valeur(13, "Roi"), AS = new Valeur(14, "As"); public String toString() { return nom; } } 29 Programmation orientée objet Rappels : final class Valeur { // [Valeur.java] Valeur.AS = new Valeur(1); int ordre; Valeur.AS.ordre = 1; String nom; Valeur(int o) { Valeur.AS.estSupérieurA(Valeur.ROI); this(o, o + ""); false! } Valeur(int o, String nom) { ordre = o; this.nom = nom; } static final Valeur SEPT = new Valeur(7), HUIT = new Valeur(8), NEUF = new Valeur(9), DIX = new Valeur(10), VALET = new Valeur(11, "Valet"), DAME = new Valeur(12, "Dame"), ROI = new Valeur(13, "Roi"), AS = new Valeur(14, "As"); boolean estSupérieureA(Valeur autre) { return this.ordre > autre.ordre; } } 30 Programmation orientée objet Le modificateur private class Valeur { // [Valeur.java] Valeur.AS = new Valeur(1); private int ordre; Valeur.AS.ordre = 1; private String nom; Valeur(int o) { Valeur.AS.estSupérieurA(Valeur.ROI); this(o, o + ""); true! } Valeur(int o, String nom) { ordre = o; this.nom = nom; } static final Valeur SEPT = new Valeur(7), HUIT = new Valeur(8), NEUF = new Valeur(9), DIX = new Valeur(10), VALET = new Valeur(11, "Valet"), DAME = new Valeur(12, "Dame"), ROI = new Valeur(13, "Roi"), AS = new Valeur(14, "As"); boolean estSupérieureA(Valeur autre) { return this.ordre > autre.ordre; } } 31 Programmation orientée objet Le modificateur private class Valeur { // [Valeur.java] class X { static public void main(String[] args) { private int ordre; Valeur v1 = new Valeur(1); private String nom; Valeur v2 = Valeur.AS; private Valeur(int o) { } this(o, o + ""); } } private Valeur(int o, String nom) { ordre = o; this.nom = nom; } static final Valeur SEPT = new Valeur(7), HUIT = new Valeur(8), NEUF = new Valeur(9), DIX = new Valeur(10), VALET = new Valeur(11, "Valet"), DAME = new Valeur(12, "Dame"), ROI = new Valeur(13, "Roi"), AS = new Valeur(14, "As"); boolean estSupérieureA(Valeur autre) { return this.ordre > autre.ordre; } } 32 Programmation orientée objet Les modificateurs Le modificateur public Membres (champ, méthode, constructeur) accessibles de n’importe où Le modificateur private Membres accessibles seulement depuis le bloc de déclaration de classe class MaClasse { // bloc de déclaration de classe } Pas de modificateur Le plus souvent => package • Membres accessibles depuis n’importe quel bloc d’une classe appartement au même paquetage Parfois public ou private selon le contexte 33 Programmation orientée objet Paquetage Un paquetage est un ensemble de classes regroupées en une unité logique, c’est l’équivalent d’une bibliothèque de classes. On peut déclarer un paquetage en début de fichier, les paquetages sont hiérarchisés. package monPaquetage.monSousPaquetage; class MaClasse { ... } Une classe dans un paquetage a accès aux classes, méthodes et champs avec droit de paquetage du même paquetage. Depuis un autre paquetage, seuls les classes, méthodes et champs public sont accessibles. package monPaquetage.monSousPaquetage; class A { ... } // seulement accessible depuis le même paquetage public class B { ... } // accessible depuis n’importe quel paquetage 34 Programmation orientée objet Paquetage: mot clé import Pour utiliser une classe d’un autre paquetage, on peut utiliser son nom qualifié. java.util.ArrayList list; On peut importer la définition d’une classe. package test; import java.util.ArrayList; class Test { ArrayList list; } On peut également importer toutes les classes d’un paquetage. import java.util.*; Deux paquetages sont importés par défaut, java.lang et le paquetage par défaut. 35 Programmation orientée objet Paquetage: organisation et compilation Dans le système de fichiers, un paquetage correspond à un dossier. Les sous-paquetages sont des sous-dossiers et les classes sont dans des fichiers qui portent leur nom. Le compilateur a besoin de cette structure pour pouvoir effectuer les liens entre classes au moment de la compilation. Les environnements de développement intégrés (Eclipse, Netbeans, …) gèrent automatiquement cet aspect du langage. Si vous compilez en ligne de commande avec javac, vous aurez probablement à utiliser les options -sourcepath et –classpath du compilateur. 36 Programmation orientée objet Bilan sur les énumérés Avec les énumérés Sans les énumérés (avant le JDK1.5) enum Couleur { TREFLE, CARREAU, CŒUR, PIQUE; } class Couleur { private String nom; private Couleur(String nom) { this.nom = nom; } static final Couleur TREFLE = new Couleur("TREFLE"), PIQUE = new Couleur("PIQUE"), COEUR = new Couleur("COEUR"), CARREAU = new Couleur("CARREAU"); Couleur - nom : String TREFLE : Couleur PIQUE : Couleur COEUR : Couleur CARREAU : Couleur - Couleur(String) + toString() : String + : public - : private rien : package public String toString() { return nom; } } 37 Programmation orientée objet Compléments sur les énumérés On peut ajouter des champs et des méthodes enum Couleur { TREFLE(true), PIQUE(true), CARREAU(false), CŒUR(false); private boolean estNoire; Couleur(boolean b) { estNoire = b; } // constructeur private! boolean estNoire() { return estNoire; } boolean estRouge() { return !estNoire; } } Test Couleur c = Couleur.TREFLE; System.out.println(c + " " + (c.estNoire() ? "noir" : "rouge")); 38 Programmation orientée objet Compléments sur les énumérés Les types énumérés sont compatibles avec l’instruction switch enum Couleur { TREFLE, PIQUE, CARREAU, CŒUR; boolean estNoire() { switch (this) { case TREFLE: case PIQUE: return true; default: return false; } } } Dans un switch, il n’est pas nécessaire de préfixer les membres de l’énumération avec son nom. 39 Programmation orientée objet Plan Méthode d’instance ou méthode de classe Constructeurs Types énumérés Les modificateurs Expressions booléennes et égalité 40 Programmation orientée objet Conditions booléennes 6 opérateurs de comparaison (int, long, float, double) < <= > >= != == inférieur inférieur ou égal supérieur supérieur ou égal différent égal 4 opérateurs logiques (boolean) && || ^ ! et logique (différent de &) ou logique (différent de |) ou exclusif logique non logique 41 Programmation orientée objet Egalité de littéraux Entiers, booléens, caractères if (x == y – 2) … Nombres approchés (float, double) true 0.1+0.1+0.1+0.1+ 0.1+0.1+0.1 == 0.7 0.1+0.1+0.1+0.1+ 0.1+0.1+0.1+0.1 == 0.8 false if (x == 0.8) … NON ! if (Math.abs(x – 0.8) < 1e-6) … OUI ! Enumérés (préfixer le littéral par le nom de l’enum !) c == Couleur.TREFLE 42 Programmation orientée objet Egalité de références Le test d’égalité entre références ne compare pas les objets ! Couleur c1 = new Couleur(1); Couleur c2 = new Couleur(1); c1 == c2 ? Couleur valeur : int c1 != c2 c1 c2 : Couleur : Couleur valeur = 1 valeur = 1 43 Programmation orientée objet Egalité de références Le test d’égalité entre références ne compare pas les objets ! Couleur c3 = new Couleur(1); Couleur c4 = c3; c3 == c4 c3 Couleur valeur : int c4 : Couleur valeur = 1 44 Programmation orientée objet Comparaison en profondeur Créer une méthode qui compare class Couleur { int valeur; Couleur(int v) { valeur = v; } boolean estLaMemeCouleurQue(Couleur c) { if (this.valeur == c.valeur) return true; else return false; } } Usage if (c1.estLaMemeCouleurQue(c2)) ... 45 Programmation orientée objet Comparaison en profondeur Créer une méthode qui compare class Couleur { int valeur; Couleur(int v) { valeur = v; } boolean estLaMemeCouleurQue(Couleur c) { return (this.valeur == c.valeur); } } Usage if (c1.estLaMemeCouleurQue(c2)) ... 46 Programmation orientée objet Comparaison en profondeur Créer une méthode qui compare class Couleur { private int valeur; Couleur(int v) { valeur = v; } boolean estLaMemeCouleurQue(Couleur c) { return (this.valeur == c.valeur); } } Usage if (c1.estLaMemeCouleurQue(c2)) ... 47 Programmation orientée objet Egalité de chaînes de caractères Les chaînes de caractères sont des références String s1 = "rouge"; String s2 = "ro" + "uge"; s1 == s2 ? s1.equals(s2) ? s1 s2 : String = "rouge" : String = "rouge" 48