Examen de Programmation Orientée Objet du 6 mai 2008 - L3

Durée : 2h. Seuls documents autorisés : ceux distribués en cours. Les énoncés et corrections des TP sont interdits.

Important : la présentation et la lisibilité du code compteront dans la note finale. Vous êtes autorisé à écrire le code (et seulement le code) avec un crayon à papier si c'est parfaitement lisible (pas de crayon trop clair).

Ajoutez des commentaires quand vous pensez que ça peut être utile au correcteur. Ne mettez pas de commentaires évidents qui n'ajoutent rien à votre code.

Critères importants pour la note : bonne utilisation du polymorphisme, encapsulation.


Cet examen comporte 2 parties. Vous rendrez les 2 parties sur 2 copies cachetées différentes.


PARTIE 1

IMPORTANT :

Vous allez modéliser la situation suivante en écrivant des classes et interfaces Java.

Ce qu'il faut modéliser, et quelques contraintes d'implantation

Une banque offre à ses clients 2 types de comptes :

Les clients sont repérés par un numéro de client. Pour chaque client vous ne retiendrez que le nom et les comptes qu'il possède, pour vous éviter d'avoir trop de code à écrire.

Un compte est repéré par un numéro. On peut savoir quel est le client qui possède un compte.

La méthode getComptes (vous choisirez la bonne classe de cette méthode) renverra tous les comptes d'un client sous la forme d'un itérateur.

Avec les 2 types de comptes, on peut

Avec un compte courant, on peut en plus

Avec un compte épargne,

Pour calculer les intérêts des sommes déposées sur un compte épargne, vous devrez enregistrer les dates et les montants des versements (obligatoire ; n'implémentez pas avec une autre façon de faire). Vous utiliserez une collection générique (au sens de la généricité étudiée dans le cours) pour enregistrer les versements (montant et date de versement).

Il n'est pas demandé de conserver un historique des versements et retraits effectués sur un compte courant.

Les exceptions

Votre code devra tenir compte de l'exception contrôlée CompteDebiteurException générée par la tentative de retrait d'une somme supérieure au solde d'un compte courant.

Question 1 (7 points)

On vous demande d'écrire toutes les classes nécessaires pour modéliser cette situation.

Rappel : si votre code comporte du code pas complètement évident à comprendre, vous devez l'expliquer par des commentaires.

IMPORTANT :

Pour vous éviter d'avoir à écrire trop de code, on ne vous demande pas d'écrire les accesseurs et les modificateurs qui n'ont rien de particulier. On ne vous demande pas non plus d'écrire les méthodes toString().

Les dates

Vous supposerez que vous disposez d'une classe fr.unice.date.Util (pas dans le même paquetage que les autres classes) qui contient une méthode de classe
long nbJours(int jourDébut, int moisDébut, int annéeDébut, int jourFin, int moisFin, int annéeFin)
qui renvoie le nombre de jours entre une date de début et une date de fin. Par exemple,
nbJours(2, 2, 2008, 3, 2, 2008)
renvoie le nombre de jours entre le 2 février 2008 et le 3 février 2008, c'est-à-dire 1.

Cette classe contient aussi 3 autres méthodes de classe qui renvoient l'année, le mois et le jour de la date du jour (la date de l'exécution du code) :
int getAnneeCourante(), int getMoisCourant(), int getJourCourant().

On ne vous demande pas d'écrire le code de cette classe Util.

Question 2 (1,5 point)

Ecrivez une classe Main dont la méthode main exécutera les actions suivantes :

Question 3 (2 points)

On souhaite garder dans la mémoire centrale tous les clients de la banque. La recherche des informations sur un client sera effectuée en donnant le numéro du client et devra être très rapide. Quelle structure de données servira à conserver les clients en mémoire centrale ? Donnez le code pour créer cette structure (indiquez avec précision à quel endroit sera situé ce code).

Donnez le code de 2 méthodes (indiquez dans quelle classe se situeront chacune des méthodes)

  1. Pour ranger un client dans la structure de données. A quel endroit pourrait être appelée cette méthode ?
  2. Pour retrouver un client à partir de son numéro.

Question 4 (1,5 point)

Un autre programmeur vous fournit une classe fr.unice.banque.Util qui contient une méthode static double totalComptes(Collection<Compte> comptes) où le type Compte représente un compte bancaire (adaptez au nom que vous avez choisi), et qui calcule le total des soldes de tous les comptes (courant ou épargne) qui sont contenus dans la collection. Vous testez la méthode avec une collection de comptes et elle fonctionne. Cependant vous essayez de l'utiliser en lui passant une collection de comptes épargne (Collection<CompteEpargne>, adaptez au nom que vous avez choisi) mais le programme ne compile pas. Donnez une raison à ce problème. Comment faudrait-il modifier la signature de la méthode pour qu'elle fonctionne avec une collection de comptes épargne ?

Question 5 (1 point)

Donnez un code qui conviendrait pour cette méthode totalComptes.

Correction

Question 1

Une erreur fréquente : dans la classe Compte, mettre une référence vers le client qui possède le compte par une variable de type int pour le numéro de client. On est ici dans le monde des objets, pas dans le monde relationnel (voir cours base de données) et il faut une référence de type Client.

Autre erreur : si on ajoute un compte à un client, il ne faut pas oublier de mettre à jour les 2 "bouts" de l'association entre Client et Compte ; il faut donc mettre à jour la variable "client" de compte mais aussi d'ajouter le compte dans la collection des comptes du client. Cette erreur n'a pas été sévèrement sanctionnée mais c'est une erreur grave.

Code des classes

Question 3

Conserver les clients dans une map dans la classe Client (ou dans une classe Banque). La clé est le numéro du client.

Une variable d'instance :

private static Map<Integer, Client> clients = new HashMap<Integer, Client>();

Une méthode de la classe Client (ou Banque) pour retrouver un client par son numéro :

public static Client getClient(int numero) {

  return clients.get(numero);

}

A la fin du constructeur de Client (pas de Banque) :

clients.put(numero, this);

Si on a mis la map dans une classe Banque, il faut aussi ajouter une méthode public pour ajouter un client et l'utiliser à la fin du constructeur de Client à la place du code de la ligne précédente.

Question 4

Voir code de la classe Util.

Le code donné par l'autre programmeur ne fonctionne pas car Collection<CompteEpargne> n'est pas un sous-type de Collection<Compte> (voir cours sur la généricité).