Question : quel est l'affichage produit par le programme suivant :
class Exo11 {
private boolean flip;
private int foo;
public Exo11(int foo) {
this.foo = foo;
flip = foo > 0;
}
public Exo11(int foo, boolean flip) {
this.foo = foo;
this.flip = flip;
}
public String toString() {
return flip + " [" + foo + "]";
}
public Exo11 flop() {
return new Exo11(-foo);
}
public Exo11 comb(Exo11 that) {
// && désigne le et logique
return new Exo11(foo - that.foo, flip && that.flip);
}
}
public class TestExo11 {
public static void main(String[] args) {
Exo11 x = new Exo11(2);
System.out.println(x);
Exo11 y = new Exo11(-2, true);
System.out.println(y.toString());
System.out.println(x.flop());
Exo11 z = y;
y = z.comb(y);
System.out.println(z);
System.out.println(y);
Exo11 w = new Exo11(3, false);
System.out.println(w.flop().flop());
System.out.println((new Exo11(3)).comb(x).flop());
}
}
On obtient l'affichage suivant :
true [2] true [-2] false [-2] true [-2] true [0] true [3] false [-1]
Question : quel est l'affichage produit par le programme suivant :
class Exo21 {
private String texte;
public Exo21() {
texte = "";
}
public void bla() {
if (texte.length() > 0) {
// s.substring(1) renvoie une nouvelle chaîne
// obtenue en supprimant le premier caractère de s
// par ex. "Toto".substring(1) donne "oto"
texte = texte.substring(1);
}
}
public void foo() {
texte = texte + String.valueOf(2 * texte.length());
}
public String toString() {
return "<- " + texte + " ->";
}
}
public class TestExo21 {
public static void main(String[] args) {
Exo21 a = new Exo21();
System.out.println(a);
a.foo();
System.out.println(a);
a.foo();
System.out.println(a);
Exo21 b = a;
String s = b.toString();
a.bla();
System.out.println(a);
System.out.println(b);
System.out.println(s);
Exo21 c = new Exo21();
for (int i = 0; i < 6; i++) {
c.foo();
}
System.out.println(c);
}
}
On obtient l'affichage suivant :
<- -> <- 0 -> <- 02 -> <- 2 -> <- 2 -> <- 02 -> <- 0246810 ->
Question : Modifiez la classe Exo21
pour rendre ses instances immuables en
gardant le même comportement général. Vous pouvez vous contenter d'écrire
les parties modifiées, sans recopier ce qui ne change pas.
Les méthodes foo
modifient l'objet appelant car elles changent la chaîne de
caractères référencée par la variable texte
. Pour rendre les instances
immuables, il suffit de modifier ces méthodes pour qu'elles renvoient un nouvel
objet Exo21
. Ce sont les deux seules méthodes qui modifient les instances et
ce sont donc les seules à modifier. On obtient la classe suivante :
public class Exo21Immuable {
private String texte;
public Exo21Immuable() {
texte = "";
}
public Exo21Immuable bla() {
if (texte.length() > 0) {
Exo21Immuable res = new Exo21Immuable();
res.texte = texte.substring(1);
return res;
} else {
return this;
}
}
public Exo21Immuable foo() {
Exo21Immuable res = new Exo21Immuable();
res.texte = texte + String.valueOf(2 * texte.length());
return res;
}
public String toString() {
return "<- " + texte + " ->";
}
}
main
.
Question : quel est l'affichage produit par le programme suivant :
class Exo31 {
private boolean[] tab;
public Exo31(int k) {
// les cases du tableau contiendront toutes false
tab = new boolean[k];
}
public void foo(int l) {
// ! est la négation logique
tab[l] = !tab[l];
}
public int bar() {
int n = 0;
for (boolean b : tab) {
if (b) {
n++;
}
}
return n;
}
public String toString() {
StringBuilder sb = new StringBuilder(tab.length + 2);
sb.append('[');
for (int i = 0; i < tab.length; i++) {
if (tab[i]) {
sb.append("X");
} else {
sb.append(".");
}
}
sb.append("]");
return sb.toString();
}
}
public class TestExo31 {
public static void main(String[] args) {
Exo31 x = new Exo31(4);
System.out.println(x);
x.foo(2);
System.out.println(x);
System.out.println(x.bar());
Exo31 y = x;
for (int i = 0; i < 4; i++) {
x.foo(i);
System.out.println(y.bar());
if (i % 2 == 0) {
y.foo(i);
}
}
System.out.println(x);
System.out.println(y);
}
}
On obtient l'affichage suivant :
[....] [..X.] 1 2 2 1 3 [.XXX] [.XXX]
Question : Quelle(s) méthode(s) doit-on modifier pour rendre immuables les instances de la
classe Exo31
? (Donnez une justification brève.)
On constate que seule la méthode foo
modifie les instances par
l'intermédiaire d'une modification d'une case du tableau tab
. Il faudrait
donc modifier cette méthode pour rendre les instances immuables.
Question : quel est l'affichage produit par le programme suivant :
class A1 {
public int f(int x) {
return 2 * x;
}
}
class B1 extends A1 {
@Override
public String toString() {
return "[B]";
}
}
class C1 extends B1 {
@Override
public int f(int x) {
return x + 3;
}
}
public class TestABC1 {
public static void main(String[] args) {
A1 a = new A1();
B1 b = new B1();
C1 c = new C1();
System.out.println(a + " -- " + b + " -- " + c);
System.out.println(a.f(2) + " -- " + b.f(4));
System.out.println(c.f(6));
Object oa = a;
Object ob = b;
Object oc = c;
System.out.println(oa + " -- " + ob + " -- " + oc);
a = b;
b = c;
System.out.println(a + " -- " + b);
System.out.println(a.f(1) + " -- " + b.f(3));
// System.out.println(oa.f(2));
}
}
On obtient l'affichage suivant :
A1@4130fafb -- [B] -- [B] 4 -- 8 9 A1@4130fafb -- [B] -- [B] [B] -- [B] 2 -- 6
Question : la dernière ligne du programme ne compile pas. Expliquez brièvement pourquoi.
Dans cette ligne, oa
est une variable de type Object
. Au moment de la
compilation, le compilateur ne peut pas connaître le type de l'objet
référencé par la variable. De ce fait, seules les méthodes définies par la
classe Object
sont utilisables. Comme la méthode f
est définie par la
classe A1
et n'est donc pas utilisable par l'intermédiaire de la variable
oa
.
Un objet de la classe Suite
ci-dessous représente des suites
\((u_n)_{n\geq 0}\) définies par récurrence par la relation \(u_{n}=au_{n-1}+b\),
pour tout \(n>0\). L'objectif de l'exercice est de compléter la classe de la
façon suivante :
a
et b
de
l'objet.valeur
doit renvoyer la valeur de numéro
n
de la suite définie par l'objet appelant (\(u_{n}\))
appliquant la relation de récurrence et en prenant \(u_0=\) u0
. On
n'utilisera pas la méthode valeurs
pour programmer valeur
(attention au « s » !).pseudoProduit
doit renvoyer un nouvel objet
Suite
dont les coefficients sont le produit par le paramètre
x
des coefficients de l'objet appelant. Par exemple si la suite
appelante est définie par \(a=2\) et \(b=1\), un appel à pseudoProduit
avec comme paramètre 2 doit produire une suite de paramètres \(a=4\) et
\(b=2\).pseudoSomme
doit renvoyer un nouvel objet
Suite
dont les coefficients \(a\) et \(b\) sont la somme des
coefficients correspondants de la suite appelant et de la suite paramètres
that
.valeurs
doit renvoyer l'ensemble des n+1
premiers termes de la suite représentée par l'objet appelant de
\(u_0=\) u0
à \(u_{n}\). On n'utilisera pas la méthode
valeur
pour programmer valeurs
(attention au « s » !).public class Suite {
private double a;
private double b;
public Suite(double a, double b) {
// À COMPLÉTER
}
public double valeur(double u0, int n) {
// À COMPLÉTER
}
public Suite pseudoProduit(double x) {
// À COMPLÉTER
}
public Suite pseudoSomme(Suite that) {
// À COMPLÉTER
}
public double[] valeurs(double u0, int n) {
// À COMPLÉTER
}
}
Une solution possible est donnée par la classe suivante :
public class Suite {
private double a;
private double b;
public Suite(double a, double b) {
this.a = a;
this.b = b;
}
public double valeur(double u0, int n) {
double u = u0;
for (int i = 1; i <= n; i++) {
u = a * u + b;
}
return u;
}
public Suite pseudoProduit(double x) {
return new Suite(a * x, b * x);
}
public Suite pseudoSomme(Suite that) {
return new Suite(a + that.a, b + that.b);
}
public double[] valeurs(double u0, int n) {
double[] res = new double[n+1];
res[0] = u0;
for (int i = 1; i <= n; i++) {
res[i] = a * res[i-1] + b;
}
return res;
}
}