Cet exercice ne nécessite pas de corrigé
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
// Ce programme calcule la surface d'un terrain composé d'un nombre arbitraire // de rectangles et de cercles. class Surfaces { public static void main (String[] args) { // Construction d'un terrain: Terrain t = new Terrain(); t.ajouterForme(new Rectangle(100, 100)); t.ajouterForme(new Cercle(50)); t.afficherSurfaceTotale(); } } class Terrain { // Tableau contenant les formes de ce terrain private Forme[] liste; // Cette variable indique combien il y a d'éléments dans le tableau private int nbFormes = 0; public Terrain () { liste = new Forme[10]; } /** * Ajoute une nouvelle Forme à la liste. * @return true si la Forme a pu être ajoutée, false si le terrain est plein */ public boolean ajouterForme(Forme forme) { if (nbFormes < liste.length) { liste[nbFormes] = forme; nbFormes++; return true; } else { return false; } } /** * Calcule la surface totale de toutes les formes * @return La surface totale */ private double calculerSurfaceTotale () { double somme = 0.0; for (int i = 0; i < nbFormes; i++) { somme += liste[i].calculerSurface(); } return somme; } public void afficherSurfaceTotale () { double surfaceTotale = calculerSurfaceTotale(); System.out.println("La surface totale est " + surfaceTotale); } } /** * Cette classe est la super-classe commune de toutes les formes géométriques. * Pour chaque forme (c'est-à-dire pour chaque sous-classe potentielle), on aimerait * pouvoir calculer la surface de celle-ci. Comme ce concept est abstrait dans le cas * d'une forme géométrique générale, on déclare la classe comme étant abstraite. */ abstract class Forme { /** * Cette méthode calcule la surface d'une forme géométrique. La responsabilité * de l'implémentation est laissée aux sous-classes. * @return La surface de la forme */ public abstract double calculerSurface(); } class Rectangle extends Forme { private double largeur; private double hauteur; public Rectangle (double largeur, double hauteur) { this.largeur = largeur; this.hauteur = hauteur; } public void setLargeur (double largeur) { this.largeur = largeur; } public double getLargeur () { return largeur; } public void setHauteur (double hauteur) { this.hauteur = hauteur; } public double getHauteur () { return hauteur; } public double calculerSurface () { return (largeur * hauteur); } } class Cercle extends Forme { private double rayon; public Cercle (double rayon) { this.rayon = rayon; } public void setRayon (double rayon) { this.rayon = rayon; } public double getRayon () { return rayon; } public double calculerSurface () { return (Math.PI * rayon * rayon); } } |
a = b; // Correct b = a; // Faux, B est une sous-classe de A a = (A)b; // Correct mais pas nécessaire a = null; // Correct null = a; // Faux, null n'est pas une variable mais une valeur a = d; // Correct b = d; // Faux, D n'hérite pas de B a = e; // Correct d = e; // Correct |
static void rechercher(A[] as) { int somme = 0; for (int i = 0; i < as.length; i++) { if (as[i] instanceof B) { somme++; } } System.out.println("Il y a " + somme + " instances de la classe B"); } |
static void additionner (A[] as) { int somme = 0; for (int i = 0; i lt as.length; i++) { if (as[i] instanceof D) { somme = somme + ((D)as[i]).d; } } System.out.println("Somme des variables d : " + somme); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
class AbstractFinal { public static void main(String[] args) { A[] tab = new A[3]; // Il n'est pas possible d'instancier une classe abstraite // tab[0] = new A(); // Faux tab[1] = new B(); // OK tab[2] = new C(); // OK // il faudrait caster, ((B)tab[1]).b = 2: // tab[1].b = 2; // Faux // Il n'est pas possible de modifier une variable finale: // ((C)tab[2]).c = 3; // Faux } } abstract class A { int a; } class B extends A { int b; } class C extends A { final double c = 1; } abstract class D extends A { double d; int operation(int a) { return (a * 2); } // Une méthode abstraite ne peut pas avoir d'instructions ou // d'accolades, seulement un point-virgule: abstract int calcul(int b); // { } // Faux abstract int machin(); } |
Les méthodes toString et equals redéfinissent (masquent) celles héritées de Object. Les tests fournis montrent qu'elles fonctionnent de façon polymorphique (affichage de rect2 et ligne commentée .2 dans la séquence "Test 3 :"). Les points auxquels il fallait être attentifs sont commentés dans la solution ci-dessous :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
class ToStringEq { public static void main(String[] args) { System.out.println("Test 1 :"); Rectangle rect = new Rectangle(12.5, 4.0); System.out.println(rect); System.out.println(); System.out.println("Test 2: "); // le type de rect1 est RectangleColore // l'objet contenu dans rect1 est de type RectangleColore RectangleColore rect1 = new RectangleColore(12.5, 4.0, "rouge"); System.out.println(rect1); System.out.println(); System.out.println("Test 3 :"); // le type de rect2 est Rectangle // l'objet contenu dans rect2 est de type RectangleColore Rectangle rect2 = new RectangleColore(25.0/2, 8.0/2, new String("rouge")); System.out.println(rect2); System.out.println (rect1.equals(rect2)); // 1. System.out.println (rect2.equals(rect1)); // 2. System.out.println(rect1.equals(null)); // 3. System.out.println (rect.equals(rect1)); // 4. System.out.println (rect1.equals(rect)); // 5. } } class Rectangle { private double largeur; private double hauteur; public Rectangle(double uneLargeur, double uneHauteur) { largeur = uneLargeur; hauteur = uneHauteur; } public boolean equals(Object autreRect) { // permet de passer correctement la ligne commentée .3 du test 3: if (autreRect == null) return false; else // garantit que l'on compare bien des // objet de même classe if (autreRect.getClass() != getClass()){ return false; } else { // procède à la comparaison attribut par // attribut return ( // Ne pas oublier le transtypage ici (largeur == ((Rectangle)autreRect).largeur) && hauteur == ((Rectangle)autreRect).hauteur); } } public String toString() { return "Rectangle : \n " + "largeur = " + largeur + "\n hauteur = " + hauteur; } } class RectangleColore extends Rectangle { private String couleur; public RectangleColore(double uneLargeur, double uneHauteur, String uneCouleur) { super(uneLargeur, uneHauteur); couleur = uneCouleur; } public boolean equals(Object autreRectColore) { if (autreRectColore == null){ return false; } else if (autreRectColore.getClass() != getClass()) { return false; } else { // Réutilisation du equals de la super-classe // pour éviter toute duplication de code return (super.equals(autreRectColore) && couleur.equals(((RectangleColore)autreRectColore).couleur) ); } } public String toString() { // Réutilisation de toString de la super-classe // pour éviter toute duplication de code return (super.toString() + "\n couleur = " + couleur); } } |
Le code complet vous est donné ci-dessous:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
/** * Une petite classe utilitaire pour commencer */ class Couleur { private char valeur; public Couleur(char c) { valeur = c; } public void afficher() { this.afficher(false); } public void afficher(boolean feminin) { switch (valeur) { case 'r': System.out.println("rouge"); break; case 'v': System.out.print("vert"); if (feminin) { System.out.println("e"); } break; case 'b': System.out.print("bleu"); if (feminin) { System.out.println("e"); } break; case 'B': System.out.print("blanc"); if (feminin) { System.out.println("he"); } break; case 'n': System.out.print("noir"); if (feminin) { System.out.println("e"); } break; } } } // ---------------------------------------------------------------------- // puis.. les classes principales abstract class Carte { private int cout; public Carte() { cout = 0; } public Carte(int cout) { this.cout = cout; } public abstract void afficher(); } // ---------------------------------------------------------------------- class Terrain extends Carte { private Couleur couleur; public Terrain(char c) { couleur = new Couleur(c); System.out.println("Un nouveau terrain."); } public void afficher() { System.out.print("Un terrain "); couleur.afficher(); System.out.println(); } } // ---------------------------------------------------------------------- class Creature extends Carte { private String nom; private int attaque; private int defense; public Creature(int cout, String nom, int attaque, int defense) { super(cout); this.nom = nom; this.attaque = attaque; this.defense = defense; System.out.println("Une nouvelle créature."); } public void afficher() { System.out.println("Une créature " + nom + " " + attaque + "/" + defense + " "); } } // ---------------------------------------------------------------------- class Sortilege extends Carte { private String nom; private String description; public Sortilege(int cout, String nom, String desc) { super(cout); this.nom = nom; this.description = desc; System.out.println("Un sortilège de plus."); } public void afficher() { System.out.println("Un sortilège " + nom + " "); } } // ---------------------------------------------------------------------- class Jeu { private int nombreCartes; private Carte[] cartes; public Jeu(int nb) { nombreCartes = nb; cartes = new Carte[nb]; System.out.println("On change de main"); } /** * Joue une carte après l'autre */ public void joue() { System.out.println("Je joue une carte..."); int i = 0; while ((cartes[i] == null) && i < nombreCartes) { i++; } if ((i < nombreCartes) && (cartes[i] != null)) { System.out.println("La carte jouée est :"); cartes[i].afficher(); cartes[i] = null; } else { System.out.println("Plus de cartes"); } } /** * Ajoute une carte à la collection */ public void piocher(Carte carte) { int i = 0; while ((i < nombreCartes) && (cartes[i] != null)) { i++; } if (i < nombreCartes) { cartes[i] = carte; } else { System.out.println("Nombre maximal de cartes atteint"); } } public void afficher() { for (int i = 0; i < nombreCartes; ++i) { if (cartes[i] != null) { cartes[i].afficher(); } } } } // ---------------------------------------------------------------------- class Magic { public static void main(String[] args) { Jeu maMain = new Jeu(10); maMain.piocher(new Terrain('b')); maMain.piocher(new Creature(6, "Golem", 4, 6)); maMain.piocher(new Sortilege(1, "Croissance Gigantesque", "La créature ciblée gagne +3/+3 jusqu'à la fin du tour")); System.out.println("Là, j'ai en stock :"); maMain.afficher(); maMain.joue(); } } |
Les constructeurs (constructeurs de copie compris) ne sont pas polymorphiques. Le programme mettra
donc dans la collection des copies d’objets de type Forme et non pas des copies des objets contenus dans
tabForm. Le programme affichera donc:
Une forme rouge Une forme jaune
Pour corriger le programme, il faut utiliser des méthodes de copie polymorphiques. Ce sont les méthodes
clone dans le code corrigé suivant :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
class Polymorph{ public static void main(String[] args){ Forme[] tabFormes = {new Cercle("rouge"), new Triangle("jaune") }; Collect formes = new Collect(10); // Une collection de formes // contenant une copie des objets definis // dans le tableau tabFormes for (int i = 0; i < tabFormes.length; ++i) formes.add(tabFormes[i].clone()); formes.dessine(); } } class Forme { private String couleur; public Forme(String uneCouleur) { couleur = uneCouleur; } public Forme clone() { return new Forme(this); } public Forme(Forme other) { this.couleur = other.couleur; } public void dessine(){ System.out.println("Une forme " + couleur); } } class Triangle extends Forme { public Triangle(String uneCouleur){ super(uneCouleur); } public Triangle(Triangle autreTriangle){ super(autreTriangle); } public Triangle clone(){ return new Triangle(this); } public void dessine(){ super.dessine(); System.out.println("toute pointue"); } } class Cercle extends Forme{ public Cercle(String uneCouleur){ super(uneCouleur); } public Cercle(Cercle autreCercle){ super(autreCercle); } public Cercle clone(){ return new Cercle(this); } public void dessine(){ super.dessine(); System.out.println("toute ronde"); } } class Collect{ private Forme collect[]; private int index; public Collect(int indexMax){ collect = new Forme[indexMax]; index = -1; } public void add(Forme a){ if (index < collect.length - 1){ ++ index; collect[index] = a; } } public void dessine(){ for (int i = 0; i <= index; ++i){ collect[i].dessine(); } } } |
Dernière mise à jour: 15/11/2024 (Revision: 1.2)