Master 2 CCI 2012-2013 |
POO,
langage Java
|
Henri
Garreta
|
Le signe © renvoie à la correction |
A. Écrivez une classe Article
pour représenter
les articles vendus dans un supermarché. Chacun comporte quatre variables
dinstance
private long reference
un numéro qui caractérise
larticle de manière uniqueprivate String intitule
la description de larticle
sous forme de texteprivate float prixHT
le prix unitaire hors taxes
de larticleprivate int quantiteEnStock
le nombre dunités
de larticle disponibleset dispose dun certain nombre de méthodes
public Article(long reference, String intitule, float prixHT,
int quantiteEnStock)
constructeur « immédiat »
qui donne une valeur à chacune des variables dinstance,public long getReference()
, public String
getIntitule()
, public float getPrixHT()
, public
int getQuantiteEnStock()
les « accesseurs »
permettant dobtenir la valeur de chaque variable dinstance public void approvisionner(int nombreUnites)
méthode pour augmenter la quantité disponible de larticlepublic boolean vendre(int nombreUnites)
cette
méthode enregistre la vente dun certain nombre dunités
de larticle, dont il faut donc diminuer en conséquence la quantité
disponible en stock.nombreUnites
est supérieur à la quantité
disponible alors le stock nest pas modifié et la méthode
renvoie false
; autrement elle renvoie true
.public float prixTTC()
cette méthode
calcule et renvoie le prix TTC de larticle public String toString()
chaîne de caractères
exprimant la référence, lintitulé et le prix de
larticle.public boolean equals(Article unArticle)
a.equals(
b)
est true si et seulement si a et b représentent le même
article (cest-à-dire sils ont la même référence).B. Pour tester cette classe écrivez une méthode main
qui crée un tableau comportant trois articles (au moins) et qui
essaie toutes ces méthodes.
N.B. Attention, la méthode equals
vraiment « correcte »
na pas exactement len-tête que nous avons utilisé ici (on verra
cela plus loin).
Pour cet exercice faites semblant de ne pas savoir quil existe dans la bibliothèque Java des classes
java.util.Date
etjava.util.Calendar
qui offrent probablement les services demandés ici.
Écrivez une classe Date
dont chaque instance représente
une date précise. Mettez-y quatre variables dinstance privées :
annee
(un entier non négatif), mois
(un entier compris entre 1 et 12), jour
(un entier compris
entre 1 et une borne supérieure qui dépend du mois) et jourSemaine
(un entier indiquant le jour de la semaine : 0 pour lundi, 1 pour mardi,
etc.
Écrivez les méthodes
public Date(int jour, int mois, int annee)
initialisation
dune date, à partir des trois nombres donnés. int getJour()
, int getMois()
, int
getAnnee()
, int getJourSemaine()
des
« accesseurs » pour obtenir les valeurs correspondantespublic String toString()
renvoie lexpression
dune date sous forme de texte, comme "vendredi 8 décembre
2006"
public boolean infeg(Date d)
comparaison : a.infeg(
b)
renvoie true
si la date a est antérieure ou égale à la date b, sinon cela renvoie false
.Pour simplifier, supposez quune année est bissextile si et seulement si son millésime est divisible par quatre (en réalité cest un peu plus compliqué).
Indications, 1 Pour abandonner le programme vous pouvez appeler
la méthode System.exit(
code)
.
Un tel traitement des erreurs est naïf, nous verrons plus loin (à
loccasion des exceptions) une meilleure manière de faire cela.
Indications, 2 Pour vous éviter de perdre votre temps
sur des choses qui ne sont pas lobjet de cet exercice, voici une expression
évaluant la validité dune date (avec la simplication sur
les années bissextiles mentionnée). Vous pouvez vous contenter
de la copier-coller dans votre programme, puis de tester la valeur de dateInvalide
:
boolean dateInvalide = mois < 1 || mois > 12 || jour < 0 || jour > 31 || jour == 31 && (mois == 4 || mois == 6 || mois == 9 || mois == 11) || jour >= 30 && mois == 2 || jour == 29 && mois == 2 && annee % 4 != 0;
Indications, 3 Pour vous éviter de perdre votre temps sur des choses qui ne sont pas lobjet de cet exercice, voici une manière simple de calculer le jour de la semaine correspondant à une date donnée (en trichant un peu par rapport à notre engagement de ne pas utiliser les outils de la bibliothèque Java) :
private int jourSemaine(int jour, int mois, int annee) { Calendar c = Calendar.getInstance(); c.set(annee, mois - 1, jour); return c.get(Calendar.DAY_OF_WEEK); }
Attention, cette méthode renvoie 1 pour dimanche, 2 pour lundi, ... 7 pour samedi.
Vous travaillez chez Bobard & Co., fabriquant exclusif du sirop Mirifik, un élixir issu de la recherche spatiale qui rend jeune, beau et intelligent et qui empêche la chute des cheveux et les tâches de transpiration. Dilué à différentes concentrations, le sirop Mirifik est commercialisé dans diverses sortes de flacons.
On vous demande décrire une classe Flacon
dont
les instances représentent les flacons de sirop Mirifik en stock.
Cette classe comportera :
private final float capacite
la capacité
du flacon (en ml) ,private float volume
le volume de liquide
(en ml) que le flacon contient à un instant donné,private float concentration
la concentration
de ce liquide, c.-à-d. le rapport (volume sirop) / (volume
sirop+eau), String etiquette
un texte libre « affiché »
sur le flaconpublic Flacon(String etiquette, float capacite)
Construction dun flacon ayant la capacité donnée
et portant létiquette indiquée. Initialement, le volume
est mis à zéro.public void verser(float volumeSirop, float volumeEau)
Ajout à un flacon des volumes de sirop et deau indiqués. public void transvaser(Flacon autreFlacon, float volume)
Ajout à un flacon du volume indiqué du liquide extrait
de lautreFlacon
indiqué.public String toString()
Production dune chaîne de caractères indiquant létiquette,
le volume et la concentration du contenu du flacon en question.Écrivez également une méthode main
pour tester toutes
ces opérations.
Que pensez-vous des qualifieurs que nous avons appliqué aux variables
dinstance ? Pourquoi capacite
a été
qualifiée final
? Est-il intéressant
de qualifier private
le volume
et la
concentration
?
N.B. Comme à lexercice précédent, pour abandonner le
programme vous pouvez appeler la méthode System.exit(
code)
.
A. Définissez une classe Point pour représenter les points du plan rapporté à une origine fixée. Les coordonnées dun point sont ici deux nombres flottants x, y, mémorisés dans deux variables dinstance privées (par exemple de type double). La classe Point comportera au moins les méthodes dinstance suivantes, toutes publiques :
|
Rappel de formules : x = r × cos(t),
y = r × sin(t), r
= sqrt(x2 + y2),
t = atan(y / x) [ou, mieux, t = atan2(y, x) ], où cos
, sin
, sqrt
, atan2
sont des méthodes statiques membres de la classe java.lang.Math
.
B. Application de la classe Point
. Une ligne
polygonale est définie par un certain nombre de points, ses sommets.
Définissez une classe LignePol pour représenter
de tels objets. Les sommets y seront mémorisés sous forme de tableau
de points. Il en découle que le nombre de sommets dune ligne
polygonale ne pourra pas augmenter au cours de la vie de celle-ci, mais cela
ne sera pas un problème dans le cadre de cet exercice.
Cette classe comportera au moins deux variables dinstance privées :
Point[] sommets
le tableau des points qui sont
les sommets de la ligne polygonale, int nbSommets
le nombre de sommets (ici, cette
information est redondante, puisque nbSommets
= sommets.length
)et les méthodes publiques :
|
En supposant (cest tout à fait fictif) que vous disposiez dun environnement graphique dans lequel on obtient le tracé du dextrémités (x0,y0) et (x1,y1) par lexpression
tracerLigne(double x0, double y0, double x1, double y1)
ajoutez à la classe LignePol une méthode tracer() qui produit le tracé de la ligne polygonale. Ensuite, écrivez une méthode main qui construit et « trace » la cocotte ci-dessus.
N.B. Pour faire tourner une sorte de simulation, vous pouvez définir :
void tracerLigne(double x0, double y0, double x1, double y1) { System.out.println("tracer de (" + x0 + "," + y0 + ") à (" + x1 + "," + y1 + ")"); }
C. Imaginons (cest de la fiction) quune enquête effectuée auprès des utilisateurs de votre classe Point a montré que cette classe est correcte et pratique mais que, du point de vue des performances, il aurait mieux valu prendre pour représentation interne des points leur coordonnées polaires (r, t) au lieu des coordonnées cartésiennes (x, y).
Réécrivez donc la classe Point de manière que les variables dinstance soient les coordonnées polaires du point, et non plus ses coordonnées cartésiennes, en respectant la contrainte suivante :
La vue publique de la classe doit être inchangée, afin que les applications de la classe Point restent valides sans nécessiter la moindre modification. Une confirmation quon a respecté cette contrainte sera que le programme de la question précédente fonctionne sans quil y ait besoin de modifier quoi que ce soit.
Cet exercice est surtout une petite réflexion sur la notion de duplication ou clonage dobjets, surtout quand il sagit dobjets qui ont pour membres dautres objets (ce qui est le cas de la majorité).
Vous devez disposer dune classe Point
, même
très simple (par exemple, celle du début de lexercice précédent).
Assurez-vous que cette classe na pas de constructeur sans arguments.
A. Un rectangle est déterminé par la donnée de deux points, respectivement son angle supérieur gauche et son angle inférieur droit. Définissez une classe Rectangle ayant deux variables dinstance privées coinNO (pour « coin Nord-Ouest ») et coinSE (pour « coin Sud-Est ») et, au moins, les méthodes suivantes :
"[(1.0,2.0);(3.0,4.0)]"
,B. Faites le test suivant :
public static void main(String[] args) { Rectangle r1, r2; r1 = new Rectangle(1, 2, 3, 4); r2 = r1; System.out.println("r1: " + r1 + ", r2: " + r2); r1.coinNO = new Point(0, 0); System.out.println("r1: " + r1 + ", r2: " + r2); r1.coinSE.homothetie(2); System.out.println("r1: " + r1 + ", r2: " + r2); }
Si on pensait que lexpression « r2 = r1;
»
affectait à r2
une duplication de r1
, quest-ce que lexécution du code précédent démontre ?
C. Écrivez la première ligne de la classe Rectangle
comme ceci
public class Rectangle implements Cloneable {
et len-tête de la fonction main
comme ceci
public static void main(String[] args) throws CloneNotSupportedException {
Maintenant remplacez la ligne « r2 = r1;
»
par
r2 = (Rectangle) r1.clone();
Votre classe utilise donc maintenant la version prédéfinie
de la méthode clone
. Reexécutez le test :
quest-ce que vous constatez ?
D. Ajoutez à votre classe la méthode suivante (vous pouvez
effacer ou non les déclarations « implements
» :
public Rectangle clone() { return new Rectangle(coinNO.x(), coinNO.y(), coinSE.x(), coinSE.y()); }
et refaites le test. Que constatez-vous à présent ?
Lobjet de cet exercice est la réalisation dune version orientée objets du bon vieux crible dEratosthène.
Le crible dEratosthène est un algorithme pour obtenir les nombres premiers inférieurs à un certain nombre n. Pour cela, on considère la suite des entiers de 2 à n. On prend le premier (2) et on fait disparaître ses multiples (4, 6, 8, etc.) ; après quoi on prend le suivant de ceux qui restent (3) et on supprime ses multiples (9, 15, 21, etc.) ; puis le suivant (5) et on enlève ses multiples (25, 35, 55, etc.) et ainsi de suite. Cest comme si 2 « mangeait » tous ses multiples, puis 3 mangeait ses multiples restants (ceux que 2 na pas mangé), puis 5 mangeait les siens, etc.
Doù lidée de définir chaque nombre premier comme un objet mangeur de nombres, ou Mangenombres. Les mangenombres sont arrangés en une sorte de liste chaînée : chacun a un successeur. De plus, sauf le premier quil faut créer « à la main », chacun est créé le moment venu par un mangenombres préexistant, son prédécesseur :
On donne 17 à manger à 2. Une opération
qui provoquera la création dun Mangenombres 17, successeur de 13.
Écrivez la classe Mangenombres, comportant
La création dun mangenombres mq doit provoquer laffichage de q.
Écrivez un programme principal affichant les nombres premiers entre 2 et un certain n. Ce programme doit créer un premier mangenombres, associé au nombre premier 2, puis exécuter une boucle dans laquelle les nombres de 2 à n sont donnés à manger à ce premier mangenombres.
La bibliothèque Java ne comporte pas de classe pour représenter les fractions (comme celles de lécole primaire, avec un numérateur et un dénominateur). On se propose ici de pallier ce manque, en définissant une classe Fraction munie des méthodes suivantes :
public Fraction(BigInteger num, BigInteger den)
constructeur basiquepublic Fraction(int n, int d)
construction dune
fraction à partir de deux entiers (quil faudra convertir en des BigInteger
)public Fraction(int n)
construction dune
fraction à partir dun entier (pour transformer un entier en fraction
on met 1 comme dénominateur)public Fraction add(Fraction f)
addition de deux
fractions public Fraction sub(Fraction f)
soustraction
de fractionspublic Fraction mult(Fraction f)
multiplication
de fractionspublic Fraction divi(Fraction f)
division de
fractionspublic String toString()
conversion dune fraction
en chaîne de caractèrespublic double doubleValue()
obtention dune valeur
décimale qui est une approximation de la fractionPour éviter les problèmes de débordement, il est conseillé de représenter le numérateur et le dénominateur dune fraction par des objets BigInteger.