Correction 9:
Polymorphisme, Typage dans une hiérarchie de classe, Modificateurs


Exercice 1: Reprise de l'exemple des figures géométriques (Polymorphisme, Niveau 0)

Cet exercice ne nécessite pas de corrigé


Exercice 2: MOOC (cours en ligne) (MOOC, Niveau 1)

Cet exercice ne nécessite pas de corrigé

Exercice 3: Calcul de surfaces 2 (Polymorphisme, Niveau 1)

  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);
    }
}


Exercice 4: Transtypage (Héritage, Niveau 1)

4.1 Debugging

  1. Erreur 1:
  2. Erreur 2:

4.2 Polymorphisme d'inclusion: un peu de pratique

Affectations entre classes

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

La méthode rechercher

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");
}

La méthode additionner

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);
}


Exercice 5: abstract et final (abstract, final, Niveau 1)

 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();
}


Exercice 6: Affichage et comparaison d'objets (toString, equals, Niveau 1)

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);
            
        }
    
}

                    
                


Exercice 7: Tour de cartes (polymorphisme, Niveau 2)

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();
    }
    
}


Exercice 8: Analyse de programme (polymorphisme, clone, Niveau 1)

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();
        }
    }
}


Exercice 9: Tutoriel I (préparation Mini-projet 2) (Fondamentaux de l'orienté-objet, Niveau 2)

Le corrigé du tutoriel est disponible en page 39.

Exercice 10: Devoir du MOOC (MOOC, Niveau 2)

Cet exercice ne nécessite pas de corrigé

Dernière mise à jour: 17/11/2023  (Revision: 1.2)