EXAMEN FINAL: Programmation JAVA
Durée: 1H30min
Soient les hiérarchies de classes suivantes:
class A { }
class B extends A { }
class C extends B { }
class X {
public void m(B b)
{ [Link](" X param B ") ; }
public void m(A a)
{ [Link](" X param A ") ; }
}
class Y extends X {
public void m(C c)
{[Link](" Y param C ") :}
public void m(B b)
{[Link](" Y param B ") ; }
}
class Z extends Y {
public void m(B b)
{[Link](" Z param B ") ;}
public void m(A a)
{[Link](" Z param A") ; }
}
Pour le code ci-dessous, donner pour chacun des 9 appels, les résultats donnés par chacune des
étapes de l'algorithme d'exécution des services d'instances en Java avec des justifications.
public class Test {
public static void main (String [] argv) {
C c = new C() ;
Bb=c;
Aa=c;
Z z = new Z() ;
Yy=z;
Xx=z;
[Link]("APPEL 1");
x.m(a) ; // appel 1
[Link]("APPEL 2");
y.m(a); // appel 2
[Link]. println("APPEL 3");
z.m(a); // appel 3
[Link]("APPEL 4");
x.m(b) ; // appel 4
[Link]("APPEL 5");
y.m(b) ; // appel 5
[Link]("APPEL 6");
z.m(b) ; // appel 6
[Link]("APPEL 7");
x.m(c) ; // appel 7
[Link]("APPEL 8");
y.m(c) ; // appel 8
[Link]("APPEL 9");
z.m(c) ; // appel 9
}
}
APPEL 1 x.m(a) affiche "X param A", car le type statique de "a" est A, et la méthode m(A a)
dans la classe X est la méthode la plus spécifique qui peut être appelée pour cet
argument.
APPEL 2 y.m(a) affiche "Y param C", car le type statique de "y" est Y et la méthode m(C c) est
la méthode la plus spécifique qui peut être appelée pour l'argument de type C (qui
est également un A).
APPEL 3 z.m(a) affiche "Z param A", car le type statique de "z" est Z, mais le type dynamique
de "a" est A et la méthode m(A a) dans la classe Z est la méthode la plus spécifique
qui peut être appelée pour cet argument.
APPEL 4 x.m(b) affiche " X param B", car le type statique de "b" est B, qui est plus spécifique
que le type statique de "x" (X), et la méthode m(B b) dans la classe X est la méthode
la plus spécifique qui peut être appelée pour cet argument.
APPEL 5 y.m(b) affiche "Y param B", car le type statique de "y" est Y, et la méthode m(B b)
dans la classe Y est la méthode la plus spécifique qui peut être appelée pour cet
argument.
APPEL 6 z.m(b) affiche "Z param B", car le type statique de "z" est Z, et la méthode m(B b)
dans la classe Z est la méthode la plus spécifique qui peut être appelée pour cet
argument.
APPEL 7 x.m(c) affiche " X param B", car le type statique de "x" est X, et la méthode m(B b)
dans la classe X est la méthode la plus spécifique qui peut être appelée pour cet
argument de type C (qui est également un B).
APPEL 8 y.m(c) affiche "Y param C", car le type statique de "y" est Y, et la méthode m(C c)
dans la classe Y est la méthode la plus spécifique qui peut être appelée pour cet
argument de type C.
APPEL 9 z.m(c) affiche "Z param B", car le type statique de "z" est Z, mais le type dynamique
de "c" est C, qui est un sous-type de B. Ainsi, la méthode m(B b) dans la classe Z est
la méthode la plus spécifique qui peut être appelée pour cet argument de type C.
EXERCICE 1 :
On a défini les classes Rational et Complex pour représenter les nombres rationnels et complexes
respectivement.
Class Rationnal {
private int num , den ;
// … Autres méthodes / attributs …
}
Class Complex {
private double re , im ;
// ... Autres méthodes / attributs …
}
On définit maintenant l'interface Squareable comme suit :
Interface Squareable {
Squareable newSquare () ; // retourne un nouveau objet qui représente le carré de l'objet actuel
void Square (); // modifie l'objet actuel x, dont l'état représente désormais ×^2
}
Modifier les définitions des classes Rational et Complex pour que le programme suivant soit
correct:
Squareable [] T = new Squareable [2] ;
T[0] = new Rational () ;
T[1] = new Complex () ;
T[0] = T[0].newSquare () ;
T[1].Square () ;
class Rational implements Squareable {
private int num, den;
// ... Autres méthodes / attributs …
public Squareable newSquare() {
Rational r = new Rational();
[Link] = [Link] * [Link];
[Link] = [Link] * [Link];
return r;
}
public void Square() {
[Link] = [Link] * [Link];
[Link] = [Link] * [Link];
}
}
class Complex implements Squareable {
private double re, im;
// ... Autres méthodes / attributs …
public Squareable newSquare() {
Complex c = new Complex();
[Link] = [Link] * [Link] - [Link] * [Link];
[Link] = 2 * [Link] * [Link];
return c;
}
public void Square() {
double reSquared = [Link] * [Link] - [Link] * [Link];
double imSquared = 2 * [Link] * [Link];
[Link] = reSquared;
[Link] = imSquared;
}}
EXERCICE 2 :
public class EntierNaturel
{
private int val;
}
1. Ecrire une classe Entier Naturel représentant les entiers naturels (ne pouvant être que >=0). Cette
classe doit implémenter :
- Un constructeur paramétré qui génère une exception de type ErrConstr si le paramètre passé
est < 0
- Un accesseur en lecture de la valeur de l'entier.
- Un accesseur en écriture de la valeur de l'entier et qui génère une exception de type ErrModif, si le
paramètre passé est <0.
- Une opération void incrémenter (EntierNaturel X) pour incrémenter un entier de la valeur de X
- Une opération void décrémenter (Entier Naturel X) pour décrémenter un entier de la valeur de X.
cette méthode génère une erreur de type ErrModif, si la décrémentation donne une valeur < 0.
- Une redéfinition de toString pour l'affichage.
2. Ecrire un programme principal pour tester les classes définies ( Instancier un EntierNaturel ,
incrémenter, modifier ensuite décrémenter,...). Aussi pour de saisir un tableau de 5 EntierNaturel et
l'affiche.
NB:
- Faite en sorte que Les classes d'exceptions mémorise la valeur qui provoque ce type
d'erreur. (par exemple : La valeur -2 est négative donc non autorisée)
- Soyez précis et commenter votre code le plus possible.
1)
public class EntierNaturel {
private int val;
// Constructeur paramétré
public EntierNaturel(int v) throws ErrConstr {
if (v < 0) {
throw new ErrConstr(v);
}
[Link] = v;
}
// Accesseur en lecture de la valeur de l'entier
public int getVal() {
return [Link];
}
// Accesseur en écriture de la valeur de l'entier
public void setVal(int v) throws ErrModif {
if (v < 0) {
throw new ErrModif(v);
}
[Link] = v;
}
// Incrémenter l'entier de la valeur de X
public void incrementer(EntierNaturel X) {
[Link] += [Link]();
}
// Décrémenter l'entier de la valeur de X
public void decrementer(EntierNaturel X) throws ErrModif {
int new_val = [Link] - [Link]();
if (new_val < 0) {
throw new ErrModif(new_val);
}
[Link] = new_val;
}
// Redéfinition de toString
@Override
public String toString() {
return [Link]([Link]);
}
}
// Classe d'exception pour la construction avec une valeur invalide
class ErrConstr extends Exception {
private int val;
public ErrConstr(int v) {
[Link] = v;
}
@Override
public String getMessage() {
return "La valeur " + [Link]([Link]) + " est négative donc non autorisée";
}
}
// Classe d'exception pour la modification avec une valeur invalide
class ErrModif extends Exception {
private int val;
public ErrModif(int v) {
[Link] = v;
}
@Override
public String getMessage() {
return "La valeur " + [Link]([Link]) + " est négative donc non autorisée";
}
}
2) Programme Principal:
import [Link];
public class TestEntierNaturel {
public static void main(String[] args) {
// Test de la classe EntierNaturel
try {
// Instanciation d'un EntierNaturel valide
EntierNaturel n1 = new EntierNaturel(3);
[Link]("n1 = " + n1); // affiche "n1 = 3"
// Modification de la valeur de n1
[Link](5);
[Link]("n1 = " + n1); // affiche "n1 = 5"
// Tentative de modification de la valeur de n1 avec une valeur invalide
[Link](-2); // génère une exception de type ErrModif
} catch (ErrConstr e) {
[Link]([Link]());
} catch (ErrModif e) {
[Link]([Link]());
}
// Test de l'incrémentation et de la décrémentation
try {
EntierNaturel n2 = new EntierNaturel(5);
[Link]("n2 = " + n2); // affiche "n2 = 5"
[Link](new EntierNaturel(2));
[Link]("n2 après incrémentation = " + n2); // affiche "n2 = 7"
[Link](new EntierNaturel(3));
[Link]("n2 après décrémentation = " + n2); // affiche "n2 = 4"
[Link](new EntierNaturel(5)); // génère une exception ErrModif
} catch (ErrConstr e) {
[Link]([Link]());
} catch (ErrModif e) {
[Link]([Link]());
}
// Saisie d'un tableau de 5 EntierNaturel et affichage
EntierNaturel[] tab = new EntierNaturel[5];
Scanner scanner = new Scanner([Link]);
try {
for (int i = 0; i < 5; i++) {
[Link]("Entrez un entier naturel : ");
int v = [Link]();
tab[i] = new EntierNaturel(v);
}
[Link]("Tableau d'EntierNaturel :");
for (int i = 0; i < 5; i++) {
[Link](tab[i]);
}
} catch (ErrConstr e) {
[Link]([Link]());
}
}
}