:: Enseignements :: ESIPE :: E3INFO :: 2013-2014 :: Programmation Objet avec Java ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) |
TP noté - programmation orientée objet avec Java
|
Le but de ce TP noté est d'écrire quelques classes simples permettant
de vérifier que vous maitrisez la mise en oeuvre des mécanismes de
base pour la création de classes et d'objets, de composition, de délégation
et de responsabilité, de sous-typage par héritage ou implémentation d'interfaces,
ainsi que l'utilisation de collections élémentaires pour la réalisation de
petits algorithmes simples en Java.
Vos sources Java produites pendant le TP devront être placées sous le répertoire
EXAM à la racine de votre compte; sinon, elles ne seront pas récupérées.
Vous pouvez consulter la javadoc à travers eclipse ou en lançant la commande
jdoc dans un shell.
Les seuls documents papiers autorisés sont les supports de cours photocopiés qui
vous ont été distribués et les notes de cours ou de TD.
On souhaite écrire des classes modélisant des articles
(en vente dans un super-marché par exemple), ainsi qu'un panier d'articles
permettant de les stocker.
Exercice 1 - Des articles (3 points)
-
Écrire une classe Item représentant un article ayant deux champs,
name pour son nom de type String et price pour
son prix en centimes de type long (on supposera que
toutes les manipulations de prix doivent se faire avec des entiers long).
Cette classe devra posséder deux accesseurs permettant d'obtenir le nom
de l'article et son prix, ainsi qu'un constructeur qui permet d'en créer
des instances.
On veut que le prix d'un article et son nom ne changent pas pour
toute la durée de vie de l'objet.
Écrire une classe Main permettant de tester la création d'un
article et le fonctionnement des accesseurs de la manière suivante:
Item item = new Item("corn flakes", 500);
System.out.println(item.getPrice()); // affiche: 500
System.out.println(item.getName()); // affiche: corn flakes
-
On souhaite que lorsque l'on affiche un article avec
System.out.println(), le nom de l'article s'affiche suivi
de deux points (":"), d'un espace et de son prix en euros, où les
centimes sont précédés d'un point ('.'), le tout suivi d'un espace
et du symbole '€'. Par exemple:
Item item = new Item("corn flakes", 500)
System.out.println(item); // affiche: corn flakes: 5.00 €
Item chewingGum = new Item("chewing gum",403);
System.out.println(chewingGum); // affiche: chewing gum: 4.03 €
Indication: utilisez la méthode String.format() qui fonctionne
comme printf(): String.format("%d.%02d", 100, 1)
produit la chaîne "100.01".
Exercice 2 - Le panier d'achats (8 points)
-
Écrire une classe ShoppingCart modélisant un panier d'articles
dans lequel on peut:
-
ajouter un article avec addItem();
-
retirer un article avec removeItem(), qui devra
renvoyer false si l'item que l'on essaye de supprimer n'existe pas;
-
connaître le nombre d'articles avec itemCount();
-
calculer le prix total du panier avec totalPrice() (vous écrirez
en commentaire au début de la méthode quel est l'ordre de grandeur de la
complexité de cette méthode);
Indication: utilisez une collection de java.util pour stocker les
articles du panier.
Modifier votre Main pour faire des tests en utilisant le code ci-dessous
Item item1 = new Item("corn flakes", 500);
Item item2 = new Item("caviar", 50000);
Item item3 = new Item("water", 101);
ShoppingCart cart = new ShoppingCart();
cart.addItem(item1);
cart.addItem(item2);
cart.addItem(item3);
System.out.println(cart.itemCount()); // affiche: 3
System.out.println(cart.totalPrice()); // affiche: 50601
-
Vérifier que le code suivant affiche bien 0.
ShoppingCart cart = new ShoppingCart();
Item item = new Item("corn flakes", 500);
cart.addItem(item);
cart.removeItem(new Item("corn flakes", 500));
System.out.println(cart.itemCount()); // affiche: 0
Sinon, changer votre implémentation en conséquence.
-
Ajouter un poids (weight de type int) exprimé en grammes
à la classe Item et modifiez le constructeur pour qu'il accepte ce paramètre.
Modifier l'implantation de votre panier pour que
l'on ne puisse pas ajouter d'article dans le panier si
le poids de ce dernier doit dépasser 10 kg.
Vous utiliserez pour cela l'exception IllegalStateException.
Attention: le test du poids devra se faire en temps constant (O(1)).
Modifier votre Main pour vérifer que cela fonctionne. Par exemple, testez:
Item item1 = new Item("corn flakes", 501, 1000);
Item item2 = new Item("caviar", 50000, 500);
Item item3 = new Item("water", 500, 5000);
ShoppingCart cart = new ShoppingCart();
cart.addItem(item1);
cart.addItem(item2);
cart.addItem(item3);
// cart.addItem(item3); // lève java.lang.IllegalStateException
cart.removeItem(new Item("eau", 500, 5000));
// cart.addItem(item3); // lève java.lang.IllegalStateException
cart.removeItem(new Item("water", 500, 5000));
cart.addItem(item3); // ajout possible!
Indication: penser que removeItem() a une valeur de retour.
-
On souhaite que chaque panier d'achat créé puisse disposer automatiquement à sa création
d'un numéro de série unique (qui commence à 1 et qui est incrémenté de 1 à chaque nouveau
panier créé), et qui soit connu comme l'identifiant (id) de ce panier.
Ajoutez une méthode getId() à la classe ShoppingCart qui retourne cet entier
de type int, et tout ce dont vous avez besoin pour l'implémenter. Par exemple,
vous pouvez tester avec le code suivant.
ShoppingCart c1 = new ShoppingCart();
System.out.println(c1.getId()); // affiche: 1
Item item1 = new Item("corn flakes", 501, 1000);
c1.addItem(item1);
Item item2 = new Item("caviar", 50000, 500);
c1.addItem(item2);
System.out.println(c1.getId()); // affiche: 1
ShoppingCart c2 = new ShoppingCart();
ShoppingCart c3 = new ShoppingCart();
Item item3 = new Item("water", 500, 5000);
c3.addItem(item3);
System.out.println(c2.getId()); // affiche: 2
System.out.println(c3.getId()); // affiche: 3
-
Ajouter à la classe ShoppingCart une méthode toString() qui
retourne une représentation du contenu du panier, commençant par l'identifiant unique du
panier et le nombre d'articles contenus, puis affichant tous les articles du panier,
un article par ligne. Par exemple, avec le code d'exemple de la question précédente,
vous devez obtenir:
System.out.println(c1); // affiche: panier 1 [2 article(s)]
// corn flakes: 5.01 €
// caviar: 500.00 €
System.out.println(c2); // affiche: panier 2 [0 article(s)]
System.out.println(c3); // affiche: panier 3 [1 article(s)]
// water: 5.00 €
Exercice 3 - Des produits frais (3 points)
Certains articles sont particulièrement frais et peuvent nécessiter la
prise en compte d'une date limite de consommation. Néanmoins,
lorsqu'on les met dans un panier d'achat, ils se comportent comme des articles
classiques et ont un nom, un prix et un poids.
-
Écrire une classe (FreshItem) qui correspond à un article frais
ayant, en plus des informations stockées dans la classe
Item, un champ bestBeforeDate de type String correspondant
à la date limite de consommation au format YYYY-MM-DD.
L'affichage d'un article frais par System.out.println() doit
afficher les informations de l'article dans le même format que pour un Item,
mais précédées de la date limite de consommation. Testez avec:
Item item1 = new Item("corn flakes", 500, 1000);
System.out.println(item1); // affiche: corn flakes: 5.00€
FreshItem fresh = new FreshItem("Salmon", 1450, 800, "2012-04-11");
System.out.println(fresh); // affiche: BBD:2012-04-11 Salmon: 14.50€
-
Verifier que le code suivant fonctionne, sinon faites les changements
qui s'imposent.
Item tin = new Item("sardine", 500, 500);
FreshItem fresh = new FreshItem("sardine", 500, 500, "2012-04-11");
ShoppingCart cart = new ShoppingCart();
cart.addItem(fresh);
cart.removeItem(tin);
System.out.println(cart); // affiche: panier 1 [1 article(s)]
// BBD: 2012-04-11 sardine: 5.00 €
Exercice 4 - La petite note (6 points)
On souhaite maintenant éditer des factures, mais pas seulement
d'articles ou d'articles frais, mais plus généralement pour une liste de
choses qui peuvent être payées.
-
Pour commencer, on représente par le type Ticket des billets d'évènements ou de
spectacles qui peuvent être vendus dans le même magasin que nos articles (Item)
ou nos articles frais (FreshItem).
Un billet est représenté par une référence (reference de type String) et
par un prix en centimes d'euros (price de type long).
Écrire une classe Ticket avec les champs nécessaires et un constructeur
permettant de créer, par exemple:
Ticket ticket = new Ticket("RGBY17032012 - Walles-France", 9000);
-
On souhaite maintenant disposer d'un type Payable, qui dispose des
méthodes:
-
label() qui retourne une String représentant une descritpion textuelle de
ce qui doit être payé;
-
cost() qui retourne le coût de ce qui doit être payé en
centimes (un entier long);
-
taxRatePerTenThousand() qui retourne la proportion du coût
qui est de la taxe, exprimée en centièmes de pourcents (en "pour-dix-mille")
sous la forme d'un entier long. Par exemple, dans cette unité, 550 représente un taux de taxe de
5,5% et 1960 représente un taux de taxe de 19,6%;
Définir le type Payable et modifier la classe Ticket de sorte que le code suivant fonctionne
(on considérera que toutes les instances de la classe Ticket sont par défaut taxées à 25%):
Payable payable = new Ticket("RGBY17032012 - Walles-France", 9000);
System.out.println(payable.label()); // affiche: RGBY17032012 - Walles-France
System.out.println(payable.cost()); // affiche: 9000
System.out.println(payable.taxRatePerTenThousand()); // affiche: 2500
-
On représente maintenant une facture comme une liste de choses à
payer. Créer une classe Invoice qui dispose pour l'instant
d'un seul constructeur sans argument et d'une unique méthode
add(Payable p) qui ajoute à la liste de choses à payer
l'argument p. Le code suivant doit fonctionner:
Invoice invoice = new Invoice();
Payable payable = new Ticket("RGBY20120317 - Walles-France", 9000);
Ticket ticket = new Ticket("MUSI20120612 - RollingStones",12000);
invoice.add(payable);
invoice.add(ticket);
-
Faites ce qu'il faut pour que la dernière ligne du code suivant
fonctionne également (toutes les instances de la classe Item
sont taxées à 10% par défaut).
Invoice invoice = new Invoice();
Payable payable = new Ticket("RGBY20120317 - Walles-France", 9000);
Ticket ticket = new Ticket("MUSI20120612 - RollingStones",12000);
invoice.add(payable);
invoice.add(ticket);
Item item = new Item("corn flakes", 500, 1000);
invoice.add(item);
-
Pour les articles frais, instances de FreshItem, la taxe est réduite de 0,1% par
tranche d'un kilo de produit.
Par exemple, les sardines en boite sont taxées à 10%, mais les sardines fraiches
sont taxées à 10% s'il y en a moins d'1 kg, et à 10% - 0,1% s'il y en a entre 1 et 2 kg...
Modifiez ce qu'il faut et vérifiez:
Item tin = new Item("sardine", 500, 500);
FreshItem fresh = new FreshItem("sardine", 500, 500, "2012-04-11");
FreshItem fresh2 = new FreshItem("sardine x3", 1500, 1500, "2012-04-11");
System.out.println(tin.taxRatePerTenThousand()); // affiche: 1000
System.out.println(fresh.taxRatePerTenThousand()); // affiche: 1000
System.out.println(fresh2.taxRatePerTenThousand()); // affiche: 990
-
On souhaite ajouter dans la classe Invoice deux méthodes:
totalAmount() qui retourne un long représentant
le montant total des choses à payer de cette facture, et
totalTax() qui retourne un long représentant le
montant total des taxes de cette facture. Que proposez vous pour
que le code suivant ne soit pas obligé de parcourir 2 fois l'ensemble
des articles de la facture.
Invoice invoice = new Invoice();
invoice.add(tin);
invoice.add(fresh);
invoice.add(fresh2);
System.out.println(invoice.totalAmount()); // affiche: 2500
System.out.println(invoice.totalTax()); // affiche: 248
© Université de Marne-la-Vallée