TD 4 Correction
TD 4 Correction
TD 4 Correction
TD n4 - Correction
Classes et H eritage
Exercice 1 (Valeurs et r ef erences, surcharge) Quache le programme suivant ? class A { private int val=0; public static void affichePlus (int a) { a++; System.out.println (a); } public static void affichePlus (A a) { a.val++; System.out.println (a.val); } public static void main (String[] args) { A uneClasse = new A (); A uneAutreClasse = new A(); affichePlus (uneClasse.val); affichePlus (uneClasse.val); affichePlus (uneClasse); affichePlus (uneClasse); affichePlus (uneAutreClasse); affichePlus (uneAutreClasse); if (uneClasse==uneAutreClasse) System.out.println("Egales"); else System.out.println("Differentes"); } } Exercice 2 (Classication) On prend les classes suivantes : Etudiant, Personne, EtudiantTravailleur, Enseignant, EtudiantSportif et Travailleur. 1. dessinez une arborescence coh erente pour ces classes en la justiant, 2. o` u se situeront les champs suivants : salaire, emploiDuTemps, anneDEtude, nom, age et sportPratique.
Exercice 3 (Surcharge, polymorphisme) Consid erez les classes Personne, Etudiant, Travailleur mentionn ees ci-dessus. Pour chaque classe ecrivez une m ethode superieur qui compare un objet ` a un autre. Une personne est sup erieure ` a une autre, si elle est plus ag ee que lautre. Un etudiant est sup erieur ` a un autre, sil etudie depuis plus longtemps. Un travailleur est sup erieur ` a un autre, si son salaire est plus grand. Quest-ce qui se passe quand on compare un etudiant avec un travailleur ? Exercice 4 (Constructeurs) Les exemples suivants sont-ils corrects ? Justiez. 1. class A { private int a; public A() { System.out.println(a); } public A(int a) { this.a = a; this(); } }
Correction : Non : dans le constructeur ` a un param` etre lappel au constructeur sans param` etre doit etre eectu e en premier.
3. class A { int a; A(int a) { this.a = a; } } class B extends A { int b; B(int a,int b) { this.a = a; this.b = b; } }
Correction : Non : En labsence dappel explicite ` a un constructeur de la super classe dans le constructeur de la classe B, un appel implicite au constructeur par d efaut de la super classe est tent e ; or la d enition dun constructeur quelconque annihile lexistence du constructeur par d efaut. La correction est donc dappeler explicitement dans la sous-classe le constructeur de la super classe : super(a) ;.
4. class A { private int a; A() {this.a=0;} } class B extends A { private int b; B() {this.a=0; this.b=0;} }
Correction : Non : La classe B na pas acc` es au champ a. Il faut utiliser le constructeur de la super classe super() ; this.b=0 ;
Exercice 5 (Red enition) Les exemples suivants sont-ils corrects ? Justiez. 1. class A { public void f() { System.out.println("Bonjour."); } } class B extends A { private void f() { System.out.println("Bonjour les amis."); } }
Correction : Non : on ne peut red enir une m ethode en restreignant sa visibilit e.
2. class A { public int f(int a) { return a++; } } class B extends A { public boolean f(int a) { return (a==0);} }
Correction : Non : on ne peut red enir une m ethode et changer le type du resultat.
3. class A { public int f(int a) { return a++; } } class B extends A { public int f(int a, int b) { return a+b;} } class test { B obj = new B(); int x = obj.f(3); int y = obj.f(3,3); }
Correction : Oui. Lappel f(3) utilise la m ethode de la super classe.
4. class A { public int f(int a) { return a++; } } class B extends A { public int f(int a, int b) { return a+b;} } class test { A obj = new B(); int x = obj.f(3); int y = obj.f(3,3); }
Correction : Non, le complilateur va r ejecter le programme car obj a et e declar e de la classe A pour le quel f est d eni sur un seul argument.
Exercice 6 (Liaison dynamique - 1) Quache le programme suivant ? class A { public String f() { return ("A");} } class B extends A { public String f() { return ("B");} } class test { public static void main (String [] args){ A a1 = new A(); A a2 = new B(); B b = new B(); System.out.println(a1.f()); System.out.println(a2.f()); System.out.println(b.f()); } }
Correction : A B B Le choix de la m ethode est fait dynamiquement pendant lex ecution.
Exercice 7 (Liaison dynamique - 2) Quache le programme suivant ? class A { public String f(B obj) { return public String f(A obj) { return } class B extends A { public String f(B obj) { return public String f(A obj) { return } class test { public static void main (String A a1 = new A(); A a2 = new B(); B b = new B(); System.out.println(a1.f(a1)); System.out.println(a1.f(a2)); System.out.println(a2.f(a1)); System.out.println(a2.f(a2)); System.out.println(a2.f(b)); System.out.println(b.f(a2)); } } ("A et B");} ("A et A");}
[] args){
Correction : A A B B B B et et et et et et A A A A B A
Le choix de la m ethode est fait dynamiquement pendant lex ecution, tandis que le type de largument est d etermin e` a la compilation.
Exercice 8 (Polymorphisme) Quache le programme suivant ? class A { public String f(D obj) { return public String f(A obj) { return } class B extends A { public String f(B obj) { return public String f(A obj) { return } class C extends B{ } class D extends B{ } class test { public static void main (String A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println(a1.f(b)); System.out.println(a1.f(c)); System.out.println(a1.f(d)); System.out.println(a2.f(b)); System.out.println(a2.f(c)); System.out.println(a2.f(d)); System.out.println(b.f(b)); System.out.println(b.f(c)); System.out.println(b.f(d)); } }
Correction : A A A B B A B B A et et et et et et et et et A A D A A D B B D
[] args){
Les premiers trois appels se comportent dune fa con polymorphe comme on sy attend. Les trois appels suivants semblent un peu bizarres cela depend du fait que la signature de la ` la compilam ethode est choisie ` a la compilation, tandis que le code ` a ex ecuter est choisi ` a lex ecution. A tion, lobjet a2 est suppos e etre de type A. Dans la classe A, la m ethode f nest pas d enie pour un objet de type B. Ainsi, lappel a2.f(b) utilise le polymorphisme et consid` ere b comme un objet de type A. Donc, ` lex la signature pour cet appel exige un argument de type A. A ecution, a2 est un objet de type B. Le
code utilis e est celui de la m ethode de B qui a la m eme signature, m eme si B pourrait avoir une m ethode ` lex plus pr ecise Lappel a2.f(d) choisit la signature de f qui exige objets de type D. A ecution, a2 est de type B. La classe B na pas une m ethode f avec la bonne signature. Donc le code de la superclasse est utilis e. Parmi les trois derniers appels, le plus interessant est le dernier : B na pas une m ethode pour D. Est-ce que D va etre vu comme un B, ou est-ce que la m ethode de la superclasse A va etre appel ee ? En faite, lh eritage a la priorit e sur le polymorphisme.
Exercice 9 (Champs de classe) Quache le programme suivant ? class A { int i; int f() { return i; } static String g() { return ("A"); } String h() { return g(); } } class B extends A { int i=2; int f() { return -i; } static String g() { return ("B"); } String h() { return g(); } } class test { public static void main(String [] args) { B b = new B(); System.out.println(b.i); System.out.println(b.f()); System.out.println(b.g()); System.out.println(b.h()); A a = b; System.out.println(a.i); System.out.println(a.f()); System.out.println(a.g()); System.out.println(a.h()); } }
Correction : 2 -2 B B 0 -2 A B La surprise est en ligne 5, o` u lon sattend ` a lire 2 (comportement des m ethodes). En r ealit e, vu qil ny a pas de dynamisme pour lacc` es aux champs, le type de lobjet est d etermin e` a la compilation
(ici A). Donc cest bien le champ de la structure A auquel on acc` ede, alors m eme que lobjet est dynamiquement un B.
Exercice 10 Dans cet exercice, on veut ecrire une classe EnsembleDEntiers fournissant des m ethodes permettant dajouter ou enlever un entier de lensemble et dacher cet ensemble : 1. donnez la liste des prototypes des constructeurs et m ethodes de la classe EnsembleDEntiers, 2. impl ementez cette classe, 3. on veut maintenant etendre cette classe en EnsembleOrdonneDEntiers dans laquelle lensemble appara tra comme toujours ordonn e (ses el ements seront visiblement ordonn es).
Correction : import java.util.Random; class EnsembleDEntiers { private int [] elements; private int nElements; private void retaille() { if (nElements<elements.length) return; int [] tmp = new int[elements.length+10]; for (int i=0; i<nElements; i++) tmp[i] = elements[i]; elements = tmp; } public EnsembleDEntiers() { elements = new int[10]; nElements = 0; } public EnsembleDEntiers(EnsembleDEntiers e) { this(); for (int i=0; i<e.nombreDElements(); i++) ajoute(e.element(i)); } public void ajoute(int element) { retaille(); elements[nElements++] = element; } private int cherche(int element) { for (int i=0; i<nombreDElements(); i++) if (element(i)==element) return i; return -1; } public int element(int indice) { return elements[indice]; } public void enleve(int element) { int indice = cherche(element); if (indice==-1) return; for (int i=indice+1; i<nombreDElements(); i++) elements[i-1] = elements[i]; nElements--; } public int nombreDElements() { return nElements;
} public String toString() { StringBuffer tmp = new StringBuffer("{"); if (nombreDElements()>0) { for (int i=0; i<nombreDElements()-1; i++) tmp.append(element(i) + ","); tmp.append(element(nombreDElements()-1)); } tmp.append("}"); return tmp.toString(); } public static void main(String [] argv) { EnsembleDEntiers e = new EnsembleOrdonneDEntiers(); Random r = new Random(); for (int i=0; i<23; i++) { e.ajoute(r.nextInt(100)); } System.out.println(e); } protected void modifie(int indice,int valeur) { elements[indice] = valeur; } } class EnsembleOrdonneDEntiers extends EnsembleDEntiers { private int cherchePremierPlusGrandOuEgal(int element) { for (int i=0; i<nombreDElements()-1; i++) if (element(i)>=element) return i; return nombreDElements()-1; } public void ajoute(int element) { super.ajoute(element); int ppg = cherchePremierPlusGrandOuEgal(element); int valeur = element(nombreDElements()-1); for (int i=nombreDElements()-1; i>ppg; i--) modifie(i,element(i-1)); modifie(ppg,valeur); } } class EnsembleFaineantOrdonneDEntiers extends EnsembleDEntiers { private boolean ordonne; public void ajoute(int element) { ordonne = false; super.ajoute(element); } public String toString() { if (!ordonne) trie(); return super.toString(); } public int element(int indice) { if (!ordonne) trie(); return super.element(indice); }
private void trie() { if (ordonne) return; // tri quelconque du tableau... ordonne = true; } }
10