1. Série A - Thème : Héritage – Opérateur
de Cast – Classes Abstraites –
Polymorphisme – Mot Clef Super –
Conception Avancée de Programme
Exercice 1 : Héritage
Soit le code suivant :
class A {
public void foo(){System.out.println(« A » ) ;}}
class B extends A {
public void foo(){System.out.println(« B» ) ;}}
Question :
Quel affichage produit la portion de code suivante :
B b = new B() ;
A a = new A() ;
A ab = new B() ;
b.foo() ;
a.foo() ;
ab.foo() ;
Exercice 2 : Bref Retour sur les notions statiques
class Point { public int x,y;
public void Point() { x=1;y=1; }}
public class Question {
public static void addx( Point p )
{ p.x += 1; }
public static void addy( Point p )
{ Point q = p;
q.y += 1; }
public static Point add( Point p, Point q )
{p.x = p.x + q.x;
p.y = p.y + q.y;
return(q); }
public static void affiche( Point p )
2. { System.out.println( "(" + p.x + "," + p.y + ")" ) ; }
public static void main( String[] arg )
{Point q = new Point();
Point p = new Point();
p.x = 2 ;
p.y = 3 ;
affiche( p ) ;
addx( p ); affiche( p );addy( p ); affiche( p );q = add( q , p ); affiche( p );
add(add( p , q ) ,p); affiche( p );}}
Exercice 3 : Héritage et Mot Clef super
class Moins {
public int n ;
public Moins(int x) { n = x ; }
public String toString() { return "Moins ! " ; }
public void test1() { System.out.println("Moins.test1 : " + this.toString());}
public void test2() { System.out.println("Moins.test2 : " + this.n); } }
class Plus extends Moins{
public int n ;
public Plus(int x, int y) { super(x) ; this.n = y ; }
public String toString() { return "Plus ! " ; }
public void test1() {
super.test1() ;
System.out.println("Plus.test1 : " + this.toString() + super.toString()); }
public void test2() {
super.test2() ;
System.out.println( "Plus.test2 : " + this.n + super.n);}
public static void main(String argv[]) {
Plus m = new Plus(1, 2) ;
m.test2() ;
Moins n = new Moins(0) ;
n.test2() ;}}
Exercice 4 : Opérateur de Forçage (Cast)
Voici le graphe de classes (graphe UML) correspondant à une hiérarchie de classes :
3. En tenant compte de cette hiérarchie, les expressions ci-dessous tentent d'être
compilées puis exécutées. Mais certaines présentent des erreurs. Pour chaque
expression, indiquez si elle est totalement sans erreur, si elle conduit à des erreurs
de compilation (et dans ce cas indiquez aussi si cela est possible la correction qui
permettrait que cette expression se compile normalement) et si elle conduit à des
erreurs d'exécution.
Attention: on considérera que toutes les classes sont concrètes (peuvent avoir des instances):
1. C1 a = new C5();
2. C1 b = new C3();
3. C2 c = a;
4. C4 d = new C1();
5. b = a;
6. b = new C6();
7. c = b;
8. d = b;
9. C4 e;
10. b = new C5();
11. e = (C4) b;
Exercice 7 : Héritage et Appel de Constructeur
Etant donné le programme suivant:
class Bidule {
int a=0;
Bidule(int x){a = x;}}
a) Indiquez ce que retournent les deux expressions suivantes (en d'autres termes,
quelle est la "valeur" de ces expressions)?
new Bidule(15)
new Bidule[15]
b) Soient les classes suivantes:
4. class Chose extends Bidule {
Chose(int x){ super(x);}}
class Truc extends Chose {
Truc(int x){ super(x);}}
Indiquez, pour chacune des expressions suivantes, si elles sont correctes ou non, et
dans ce cas, quel type d'erreur produisent-elles (et est ce une erreur de compilation,
ou d'exécution) et comment peut on faire pour qu'elles ne produisent plus d'erreur?
Chose c1 = new Truc(10);
Bidule c2 = c1;
Truc c3 = c1;
Exercice 8 : Héritage et instanciation
Soient les classes suivantes:
class Bouteille { public void deboucher() { this.bruit(); }
void bruit(){ System.out.println("clink"); } }
class BouteilleSansAlcool extends Bouteille{ }
class BouteilleJusFruit extends BouteilleSansAlcool { }
class BouteilleSoda extends BouteilleSansAlcool { void bruit(){
System.out.println("psshit"); } }
class BouteilleEau extends BouteilleSansAlcool { }
class BouteilleAlcool extends Bouteille { void bruit(){ System.out.println("blup");
}}
class BouteilleVin extends BouteilleA { void bruit(){ System.out.println("pop");
}}
class BouteilleChampagne extends BouteilleV { void bruit(){
System.out.println("paan"); } }
class BouteilleWhisky extends BouteilleA { }
Question 1:
Donnez ce qui est affiché (ou si vous préférez ce qui est imprimé dans le flux de
sortie de la console) par le programme suivant:
main() {
Bouteille b1 = new Bouteille();
Bouteille b2 = new BouteilleSansAlcool();
BouteilleAlcool b3 = new BouteilleAlcool();
BouteilleAlcool b4 = new BouteilleChampagne();
BouteilleVin b5 = new BouteilleChampagne();
BouteilleWhisky b6 = new BouteilleWhisky();
5. BouteilleAlcool b7 = new BouteilleVin();
Bouteille b8 = new BouteilleChampagne();
b1.deboucher();
b2.deboucher();
b3.deboucher();
b4.deboucher();
b5.deboucher(); b6.deboucher(); b7.deboucher(); b8.deboucher(); }
Question 2:
On effectue les affectations suivantes (ces affectations sont indépendantes les unes
des autres, elles ne sont pas exécutées en séquence!). Pour chaque affectation, dites
si elle fonctionne sans erreur, si elle provoque une erreur à la compilation ou si elle
provoque une erreur à l'exécution. Dans ce cas, expliquez (brièvement) l'origine de
ces erreurs. S'il y a une erreur à la compilation, indiquez si l'on peut ajouter ou
supprimer quelque chose qui évite cette erreur sans que cela modifie le sens du
programme. (note: ces affectations sont faites dans l'ordre!).
1. b1 = b2;
2. b1 = b4;
3. b3 = b4;
4. b3 = b5;
5. b5 = b4;
6. b7 = b6;
7. b7 = b4;
8. b6 = (BouteilleWhisky) b4;
9. b5 = (BouteilleChampagne) b7;
10. b8 = b2;
Question 3:
On crée un tableau de bouteilles de la manière suivante:
BouteilleAlcool[] e = new BouteilleAlcool[4];
a) Que faut il faire pour que les affectations suivantes soient toutes valides (à la
compilation et à l'exécution).
Note: on reprendra les variables dans l'état de la fin de la question 1):
e[0] = b4; e[1] = b5; e[2] = b6; e[3] = b7;
b) Que produit l'exécution de l'instruction suivante:
for(int i=0;i<e.length;i++) e[i].deboucher();
Exercice 10 : Héritage et instanciation
Soient les classes suivantes:
class Personne {
public void parler() {
System.out.println("hum!");} }
6. class Adulte extends Personne{
public void parler() {
System.out.println("Bonjour tout le monde!");}}
class AdulteDistinguee extends Adulte {
public void parler() {
System.out.println("Mes chers amis, bonjour!");}}
class Jeune extends Personne { }
class Ado extends Jeune {
public void parler() {
System.out.println("salut les mecs!");}}
class Enfant extends Jeune {}
class Bebe extends Enfant {
public void parler() {
System.out.println("J'chui pas un bebe!");}}
class BebeCadum extends Bebe {
public void parler() {
System.out.println("Agheu, agheu!");}}
Question 1:
Donnez ce qui est affiché par le programme suivant:
main() {
Personne P1 = new Personne();
Personne P2 = new AdulteDistinguee();
Adulte P3 = new AdulteDistingue();
Personne P4 = new Bebe();
Jeune P5 = new Ado();
Enfant P6 = new BebeCadum();
BebeCadum P7 = new BebeCadum();
Enfant P8 = new Bebe();
P1.parler();
P2.parler();
P3.parler();
P4.parler();
P5.parler();
P6.parler();
P7.parler();
P8.parler();}
Question 2:
On effectue les affectations suivantes (ces affectations sont indépendantes les unes
7. des autres, elles ne sont pas exécutées en séquence!). Pour chaque affectation, dites
si
elle fonctionne sans erreur, si elle provoque une erreur à la compilation ou si elle
provoque une erreur à l'exécution. Si il y a une erreur expliquez (rapidement)
pourquoi.
1. P1 = P2;
2. P4 = P1;
3. P3 = P4;
4. P3 = P1;
5. P4 = P5;
6. p7 = p6;
7. p7 = (BebeCadum) p4;
8. p6 = (Bebe) p4;
9. p3 = (AdulteDistingue) p2;
10.p8 = (Bebe) p5;
Question 3:
On crée un tableau d'enfants de la manière suivante:
Jeune[] e = new Jeune[4];
a) Que faut il faire pour que les affectations suivantes soient toutes valides (à la
compilation et à l'exécution). Note: on reprendra les variables dans l'état de la
question 1):
e[0] = p4;
e[1] = p5;
e[2] = p6;
e[3] = p7;
e[4] = p8;
b) Que produit l'exécution de l'instruction suivante:
for(int i=0;i<e.length;i++)
e[i].parler();
c) Que faut il faire pour que les affectations suivantes soient toutes valides (à la
compilation et à l'exécution):
p5 = e[0];
p4 = e[1];
p7 = e[2];
p8 = e[3];
p6 = e[4];
Exercice 11 : Héritage et envoi de message
On désire réaliser un logiciel de dessin en Java en utilisant la technique objet sans utiliser le package
java.awt ou swing de Java. Un dessin est défini par les coordonnées de deux de ses points, (x1, y1, x2,
8. y2) et sa méthode dessineToi(). La figure suivante montre un dessin avec ses coordonnées (On ne
tiendra pas compte des problèmes liés au Graphics. On suppose qu'il n'y a plus de Graphics...).
On suppose que les classes suivantes sont déjà définies (en Java):
import java.util.*;
abstract class Dessin extends Object {
int x1, y1, x2, y2;
abstract void dessineToi(); // doit etre redefinie
Dessin(int _x1, int _y1, int _x2, int _y2) {
x1 = _x1; x2 = _x2;
y1 = _y1; y2 = _y2;
}
}
class DessinComplexe extends Dessin {
Vector dessins = new Vector();
void ajoute(Dessin d) {
dessins.addElement(d); // ajoute un dessin
}
void dessineToi() {
//à définir
}
}
class DessinElementaire extends Dessin {
}
class Rectangle extends DessinElementaire {
Rectangle(int g, int h, int b, int d) {
Dessin(g, h, b, d);
}
void dessineToi () {
// c'est une primitive
}}
class Ligne extends DessinElementaire {
Ligne(int xp1, int yp1, int xp2, int yp2) {
Dessin(xp1, yp1, xp2, yp2);
}
void dessineToi () {
// c'est aussi une primitive
9. }}
Question A
Donnez le code de la méthode dessineToi() dans DessinComplex
Question B
On veut dessiner le dessin complexe dc1 suivant comprenant 2 rectangles et 1 ligne,
les
rectangles et la ligne étant définis ainsi:
Rectangle r1 = new Rectangle(10,10,20,40);
Rectangle r2 = new Rectangle(5,25,50,60);
Ligne l1 = new Ligne(5,35,45,10);
Donnez le code de l'instanciation permettant de construire dc1.
Question C
On désire réaliser la classe DoubleLigne qui comprend 2 lignes reliées entre elles,
comme le montre la figure suivante:
Une instance de cette ligne est définie ainsi:
DoubleLigne dl1=DoubleLigne(5,10,30,35,20,60);
Question: Définissez la classe DoubleLigne avec ses champs et ses méthodes (on
donnera le code des méthodes). Note: il existe plusieurs manières de construire une
telle classe. Produisez en simplement une.
Question D
On désire calculer le centre d'un dessin. On suppose alors que la classe Dessin est
modifiée ainsi (les parties modifiées sont en italique):
class Dessin extends Object {
int x1, y1, x2, y2;
int cx, cy; // coordonnées du centre du dessin
dessineToi() {}
abstract Entier largeur(); // méthode abstraite
abstract Entier hauteur(); // méthode abstraite
10. calculCentre(){...};
}
1) Donnez le code de l'ensemble des méthodes hauteur() et largeur() dans
DessinElementaire et DessinComplexe, de telle manière que l'on puisse calculer la
hauteur ou la largeur de n'importe quel dessin. Ex:
// calcul la largeur du rectangle r1 c'est-à-dire la différence des
abscisses des deux points de r1
r1.largeur();
// calcule la "hauteur" de la ligne, c'est-à-dire la différence des
ordonnées des deux points de r1
l1.hauteur();
// calcule la largeur totale du dessin complexe dc1.
dc1.largeur();
2) Donnez le code de la méthode calculCentre dans la classe Dessin.