Vous êtes sur la page 1sur 5

Master 2 BBSG

POO, langage Java

Laurent Tichit

4. Classes abstraites, interfaces


1. Abstraction, classes abstraites, interfaces
2. Interfaces et objets fonctionnels
3. Hritage multiple et Java

4.1 Abstraction, classes abstraites, interfaces


Dans cet exercice on vous demande de dfinir un ensemble de classes pour reprsenter des fonctions
dune variable formes avec des constantes, des occurrences de la variable x, les quatre oprations
arithmtiques +, , , / et des appels de quelques fonctions convenues comme sin, cos exp, log, etc. Par
exemple :
12 x + sin(3x 5)
Dans un programme, une expression comme celle-l peut tre efficacement reprsente
par une structure arborescente, organise comme le montre la figure ci-contre, faite de
feuilles (les constantes et les variables), de nuds deux descendants (les
oprateurs binaires) et de nuds un descendant (les fonctions dune variable).
Les classes quil faut dfinir sont destines reprsenter les nuds dun tel arbre. Il y
en a donc de plusieurs sortes :
un nud reprsentant une constante porte un nombre, la valeur de la constante,
un nud reprsentant une occurrence de la variable x ne porte aucune autre
information,
un nud reprsentant une addition, une soustraction, une multiplication ou une
division porte deux informations : les expressions qui sont ses oprandes,
un nud reprsentant lappel dune fonction porte comme information
lexpressions qui est son argument.
Dfinissez les classes suivantes (la marge traduit la relation implements ou extends) :
Expression interface reprsentant ce quont en commun toutes les expressions
arithmtiques (cest--dire toutes les sortes de nuds de notre structure arborescente) : elle se
compose dune seule mthode :
public double valeur(double x);

qui renvoie la valeur de lexpression pour la valeur de x donne. Bien entendu, toutes
les classes concrtes de cette hirarchie devront fournir une dfinition de la mthode
valeur. Elles fourniront aussi une refinition intressante de la mthode String
toString().
Constante classe concrte dont chaque instance reprsente une occurrence dune
constante. Cette classe a un membre : la valeur de la constante.
Variable classe concrte dont chaque instance reprsente une occurrence de la

variable x. Cette classe na besoin daucun membre.


OperationBinaire classe abstraite rassemblant ce quont en commun tous les
oprateurs deux oprandes. Elle a donc deux membres dinstance, de type
Expression, reprsentant les deux oprandes, et le constructeur qui va avec.
Addition, Soustraction, Multiplication, Division classes
concrtes pour reprsenter les oprations binaires. Cest ici quon trouve une
dfinition pertinente de la mthode valeur promise dans linterface
Expression.
OperationUnaire classe abstraite rassemblant ce quont en commun tous les
oprateurs un oprande. Elle doit avoir un membre dinstance, de type Expression,
reprsentant loprande en question.
Sin, Cos, Log, Exp, etc. classes concrtes pour reprsenter les fonctions
standard. Ici on doit trouver une dfinition pertinente de la mthode valeur
promise dans linterface Expression.
On ne vous demande pas de rsoudre le problme (difficile) de la lecture dun tel arbre, cest--dire de
sa construction partir dun texte, par exemple lu la console. En revanche, vous devez montrer que
votre structure est bien adapte au calcul de la valeur de lexpression pour une valeur donne de la
variable x. Pour cela, on excutera un programme dessai comme celui-ci :
...
public static void main(String[] args) {
/* codage de la fonction f(x) = 2 * sin(x) + 3 * cos(x) */
Expression f = new Addition(
new Multiplication(
new Constante(2), new Sin(new Variable())),
new Multiplication(
new Constante(3), new Cos(new Variable())));
/* calcul de la valeur de f(x) pour quelques valeurs de x */
double[] tab = { 0, 0.5, 1, 1.5, 2, 2.5 };

}
...

for (int i = 0; i < tab.length; i++) {


double x = tab[i];
System.out.println("f(" + x + ") = " + f.valeur(x));
}

Lexcution de ce programme produit laffichage de :


f(0.0)
f(0.5)
f(1.0)
f(1.5)
f(2.0)
f(2.5)

=
=
=
=
=
=

3.0
3.5915987628795243
3.3038488872202123
2.2072015782112175
0.5701543440099361
-1.2064865584328883

4.2 Interfaces et objets fonctionnels


On sattaque ici au problme suivant : quelquefois il est utile quune fonction puisse avoir pour argument
une autre fonction. Comment obtenir cela en Java ?

Par exemple, la mthode dite par dichotomie est une technique de rsolution approche de lquation
f(x) = 0 . Sous rserve que f soit une fonction continue (cest--dire sans sauts ) et quon connaisse
deux valeurs a et b telles que les signes de f(a) et de f(b) soient opposs, alors cette mthode trouve
rapidement une valeur z, comprise entre a et b, qui nest pas plus loigne que epsilon dune solution de
lquation f(x) = 0, o epsilon est une prcision arbitraire fixe lavance. Dit autrement : la mthode
trouve z tel que f(z) = 0 avec une erreur infrieure epsilon.
Lalgorithme est bien connu ; en voici une programmation accompagne dun essai consistant rsoudre
x2 4 = 0 (c.--d. trouver la racine carre de 4) avec une prcision de 10 -12 ( lexcution, ce
programme affiche 1.9999999999995453) :
public class TestDichotomie {
/* lappel de la mthode */
public static void main(String[] args) {
double y = zero(0, 4, 1e-12);
System.out.println(y);
}
/* la fonction f(x) = x * x - 4 */
static double f(double x) {
return x * x - 4;
}
/* la mthode elle mme (on suppose que f(a) et f(b) sont de signes
distincts) */
static double zero(double a, double b, double epsilon) {
/* si on na pas f(a) < 0 on change a et b */
if (f(a) > 0) {
double w = a; a = b; b = w;
}
/* on itre jusqu avoir |a - b| <= epsilon */
while (Math.abs(b - a) > epsilon) {
double c = (a + b) / 2;
if (f(c) < 0)
a = c;
else
b = c;
}
/* lorsque |a - b| <= epsilon, toute valeur comprise entre a et
b convient */
return (a + b) / 2;
}
}

crite comme cela, la mthode zero fonctionne mais elle est peu rutilisable, car elle emploie une
fonction f qui ne figure pas parmi ses arguments. Pour trouver un zro dune autre fonction il faut
changer le corps de f et recompiler ce programme ! Plus grave, puisque f est fig, on ne peut pas dans le
mme programme utiliser zero sur des fonctions diffrentes.
On va donc faire en sorte dcrire la mthode zro avec la fonction parmi les arguments, cest--dire avec
len-tte
static double zero(Fonction f, double a, double b, double epsilon)

o Fonction reprsente le concept de fonction, cest--dire ce que toutes les fonctions ont en
commun. Pour ce qui nous intresse ici, ce que les fonctions ont en commun est la possibilit dtre
appeles avec un double pour argument, et de renvoyer alors un double comme rsultat. On introduit
donc linterface :

public interface Fonction {


double appel(double x);
}

Exercice. Rcrivez la mthode zero en prenant un objet Fonction comme premier argument, ensuite
crivez une fonction main qui rsout lquation cos(x) = x avec une erreur infrieure 10-10. Il vous
faudra donc dcfinir un objet Fonction dont la mthode appel se rduit return
cos(x) x; .
crivez lessai (la mthode main) de deux manires, sans utiliser puis en utilisant les classes anonymes.

4.3 Hritage multiple et Java


En Java lhritage est simple : chaque classe a une et une seule super-classe (sauf Object, qui na pas de
super-classe). Mais alors, comment faire lorsque les objets dun certain type doivent tre considrs
comme appartenant deux hirarchies dhritage, ou plus ?
Question annexe : pourquoi serait-on oblig de dclarer une classe C comme hritant de deux
autres classes A et B ? Cest--dire, si on veut que les membres de A et ceux de B soient
membres de C, pourquoi ne suffit-il pas de mettre dans C une variable de type A et une
variable de type B ?
Rponse. Il est ncessaire que C soit sous-classe de A [resp. B] si on veut pouvoir mettre un
objet C un endroit o un objet A [resp. B] est prvu. Par exemple, si on dispose dune
mthode dclare avec un argument formel de type A [resp. B] et quon veut lappeler avec un
argument effectif de type C alors il faut que la classe C soit sous-classe de A [resp. B].
Exemple (un peu tir par les cheveux, vrai dire, mais cest un exemple...) :
un Personnel est un fonctionnaire relevant du MENESR (Ministre de lducation Nationale,
de lEnseignement Suprieur et de la Recherche) ; il est dfini par un certain nombre de variables
dinstances prives, chacune associe une mthode publique de mme nom qui permet den
obtenir la valeur :
nom (de type String),
numeroSS (de type long),
anneeNaissance (de type int),
etc.
un Enseignant est une entit pouvant dispenser des cours ; cela peut tre un personnel de
lducation nationale, mais pas ncessairement (un cours peut tre donn par un intervenant
extrieur, un magntoscope, un ne parlant...) ; comme prcdemment, cela se dfinit par un
ensemble de variables dinstance prives avec des mthodes publiques daccs
matiere (de type String),
classeNiveau (de type int),
etc.
un Chercheur est une autre entit non ncessairement membre de lducation nationale,
consacrant une partie de son temps des recherches ; encore une fois, des variables dinstance
prives et des mthodes publiques daccs :
domaineDeRecherches (de type String),
nombrePublications (de type int)
etc.
Nous supposerons que Personnel, Enseignant et Chercheur sont trois classes concrtes,
prcdemment dfinies et parfaitement oprationnelles. En outre, nous supposerons que des mthodes
sont disponibles par ailleurs, qui prennent pour argument des objets de chacune de ces trois classes :

static void gestionCarriere(Personnel unPersonnel);


static void emploiDuTemps(Enseignant unEnseignant);
static void rapportActivite(Chercheur unChercheur);

A - Pour l'exercice, dfinissez ces mthodes (dans une autre classe), et affichez simplement quelques
attribut de l'argument pass en paramtre. Instanciez dans votre main quelques Personnel,
Enseignant et Chercheur, et testez ces trois mthodes.
B- Maintenant on aimerait acoir des objets qui soient la fois des Personnels, des Enseignants et des
Chercheurs et qu'on puisse passer chacune des trois mthodes. Il va donc falloir modifier notre code.
Lexercice est le suivant : dfinir une classe UnPersonnelEnseignantChercheur destine
reprsenter des personnels de lducation nationale qui sont en mme temps des enseignants et des
chercheurs. Il faut utiliser les trois classes Personnel, Enseignant et Chercheur, et la nouvelle
classe doit tre dfinie de telle manire que ses instances puissent tre donnes pour argument aux
mthodes ci-dessus, ventuellement au prix dun (trs lger) changement de nom de certains types.
L'ide gnrale est de parler de comportements qui sont au nombre de 3 et qui seront des interfaces. Ce
sont elles qui, dans l'ultime version du code seront appelles Personnel, Enseignant et
Chercheur. Les classes concretes seront nommes UnPersonnel, UnEnseignant et
UnChercheur. On pourra de la mme manire crer des classes UnPersonnelEnseignant,
UnEnseignantChercheur et UnPersonnelChercheur. Ces classes concretes implmenteront 2
des trois interfaces et les mthodes static ci-dessus doivent donc dsormais, sans aucun changement,
fonctionner avec deux objets de type diffrent.

Vous aimerez peut-être aussi