Énoncé 6 : Interactions complexes et héritage entre objets
Introduction
Durée
4 heures 30
Mots-clés
héritage, polymorphisme, classe abstraite, méthode abstraite, classe concrète, interface
Objectif
Dans ce chapitre, vous apprendrez à :
-
réaliser des interactions complexes entre des objets ;
-
mettre en œuvre l’héritage ;
-
utiliser le polymorphisme ;
-
écrire des classes et des méthodes abstraites.
Prérequis
Pour valider les prérequis nécessaires avant d’aborder le TP, répondez aux questions ci-après.
1. Questions générales
|
1. |
En quoi consiste l’héritage entre deux classes en ce qui concerne les attributs et les méthodes ? |
|
|
2. |
Qu’est-ce qu’une sous-classe et une surclasse ? |
|
|
3. |
Que peut référencer une variable typée par une classe C ? |
|
|
|
a. |
un objet de la classe C ; |
|
|
b. |
un objet d’une sous-classe de C ; |
|
|
c. |
un objet d’une surclasse de C ; |
|
|
d. |
un objet de toute classe possédant un attribut typé par C et qui n’est ni une surclasse ni une sous-classe de C. |
|
4. |
Que signifie le polymorphisme ? |
|
|
|
a. |
Une classe peut introduire plusieurs attributs de même nom. |
|
|
b. |
Une classe peut introduire plusieurs méthodes de même nom. |
|
|
c. |
Une variable (ou un paramètre) peut référencer des objets de classes différentes. De ce fait, un appel vers l’objet référencé peut conduire à des comportements différents en fonction de la classe de cet objet. |
|
5. |
Qu’est-ce qu’une méthode abstraite ? |
|
|
6. |
Qu’est-ce qu’une classe abstraite et quelle est son utilité ? |
|
|
7. |
Qu’est-ce qu’une classe concrète ? |
|
2. Questions Java
|
8. |
Qu’est-ce qu’une interface ?... | |
Énoncé 6.1 : La classe Automobile
Durée estimative : 20 minutes
Une automobile est constituée d’un moteur relié aux deux roues motrices. La représentation objet de cette automobile va nécessiter trois classes :
-
la classe Automobile ;
-
la classe Moteur ;
-
la classe Roue.
Écrivez en Java/Python ces trois classes telles qu’elles vérifient les points suivants :
-
Le constructeur de la classe Automobile crée un nouvel objet de la classe Moteur. Le constructeur doit également lier ce nouvel objet Moteur à l’objet Automobile.
-
Le constructeur de la classe Moteur crée deux nouveaux objets de la classe Roue qui correspondent à la roue gauche et à la roue droite de l’automobile. Le constructeur doit également lier les deux objets Roue à l’objet Moteur.
-
Le constructeur de chaque classe prend également comme paramètre une chaîne de caractères qui est le nom de l’objet. Ce nom est stocké dans l’attribut nom de chaque classe.
-
La classe Automobile possède une méthode demarre qui demande à son tour au moteur de démarrer. La méthode demarre de la classe Moteur demande à chaque roue de tourner en invoquant leur méthode tourne. Les méthodes de démarrage débutent en affichant un message indiquant que l’objet...
Énoncé 6.2 : La classe Devine2
Durée estimative : 35 minutes
Réécrivez en Java/Python la classe Devine de l’exercice 4.13 en la renommant Devine2 telle qu’elle ne possède plus aucune entrée-sortie avec l’utilisateur. La méthode session est remplacée par la méthode propose qui prend un entier en paramètre et renvoie :
-
0 si la valeur est égale au nombre à deviner ;
-
1 si la valeur est strictement supérieure au nombre à deviner ;
-
-1 si la valeur est strictement inférieure au nombre à deviner.
La classe Devine2 introduit quatre autres méthodes ne prenant pas de paramètres :
-
initialise qui recalcule un nombre à deviner et remet à zéro le nombre de tentatives ;
-
getNombreTentatives (Java)/get_nombre_tentatives (Python) qui renvoie le nombre d’appels à la méthode propose depuis le dernier appel à la méthode initialise ;
-
getBorneInf (Java)/get_borne_inf (Python) qui renvoie la borne inférieure de l’intervalle dans lequel se trouve le nombre à deviner ;
-
getBorneSup (Java)/get_borne_sup(Python) qui renvoie la borne supérieure dudit intervalle.
Écrivez ensuite la classe DevineES possédant le même constructeur et la même méthode session que la classe...
Énoncé 6.3 : La classe DevineNombre
Durée estimative : 30 minutes
Écrivez en Java/Python les classes DevineNombre et DevineNombreES. La classe DevineNombre possède la méthode devine qui cherche à trouver un nombre compris entre deux bornes transmises en paramètre. Cette méthode n’a aucune interaction avec l’utilisateur. Lorsqu’une proposition est calculée, elle est transmise en paramètre à la méthode propose d’un objet de la classe DevineNombreES qui se charge de réaliser l’interaction avec l’utilisateur. La méthode propose prend un entier en paramètre et renvoie :
-
0 si la valeur est égale au nombre à deviner ;
-
1 si la valeur est strictement supérieure au nombre à deviner ;
-
-1 si la valeur est strictement inférieure au nombre à deviner.
L’objet de la classe DevineNombreES qui est utilisé au sein de la classe DevineNombre est créé dans le constructeur de cette dernière.
Écrivez enfin un programme Java/Python chargé de tester les classes DevineNombre et DevineNombreES.
Indice
Pour écrire la méthode devine, vous pouvez vous inspirer de l’exercice 1.12. Attention, le nombre que l’ordinateur doit deviner peut maintenant être pair ou impair.
Énoncé 6.4 : L’ordinateur joue contre l’ordinateur
Durée estimative : 25 minutes
Dans cet exercice, un objet calcule un nombre aléatoire qu’un autre objet va deviner. Vous devez vous baser sur les classes Devine2 et DevineNombre.
Écrivez en Java/Python la classe LienDevine dont les objets connectent un objet de DevineNombre à un objet de Devine2. La classe LienDevine possède les méthodes suivantes :
-
un constructeur prenant en paramètre un objet de type NombreAleatoire (introduit à l’exercice 4.4) et créant un objet de la classe Devine2 ;
-
la méthode propose qui invoque la méthode propose de l’objet de Devine2, tout en affichant à l’écran la proposition puis le résultat de la comparaison afin de pouvoir suivre l’évolution du programme lors de son exécution ;
-
la méthode initialise qui invoque la méthode initialise de l’objet de Devine2 ;
-
la méthode getNombreTentatives (Java)/get_nombre_tentatives (Python) qui invoque la méthode de même nom de l’objet de Devine2.
Réécrivez la classe DevineNombre en la renommant DevineNombre2 pour qu’elle interagisse avec un objet de LienDevine au lieu d’un objet de DevineNombreES. Son constructeur est modifié en conséquence. Il reçoit...
Énoncé 6.5 : La course automobile
Durée estimative : 60 minutes
L’exercice est basé sur la nouvelle classe NombreAleatoireCourse qui utilise un générateur de nombres aléatoires de la bibliothèque standard.
La description en Java de cette classe basée sur la classe Random est la suivante :
import java.util.Random;
public class NombreAleatoireCourse {
Random r = new Random();
public NombreAleatoireCourse() {
r.setSeed(System.currentTimeMillis());
}
public int calcule(int borneInf, int borneSup) {
return borneInf + (int) (r.nextDouble() * (borneSup - borneInf + 1));
}
}
La description de cette classe en Python qui s’appuie sur la fonction random est la suivante :
import random
from time import time
class NombreAleatoireCourse:
def __init__(self) -> None:
random.seed(time())
def calcule(self, borne_inf: int, borne_sup: int) -> int:
return borne_inf + int(random.random() *
(borne_sup - borne_inf + 1))
Écrivez en Java/Python la classe Automobile qui va décrire une automobile. Cette classe introduit les...
Énoncé 6.6 : La classe Complexe2
Durée estimative : 15 minutes
Réécrivez en Java/Python la classe Complexe2 de l’exercice 4.6 en tant que sous-classe de la classe Complexe telle qu’elle est définie dans le corrigé de l’exercice 5.6 avec la méthode toString (Java)/__str__ (Python).
La méthode ajouteComplexe (Java)/ajoute_complexe (Python) ainsi que la méthode multiplieComplexe (Java)/multiple_complexe (Python) prennent dans ce cas un objet de la classe Complexe en paramètre.
Le programme principal écrit dans l’exercice 4.6 fonctionne tout à fait correctement avec cette nouvelle version de la classe Complexe2. Expliquez pourquoi.
Réécrivez maintenant ce programme principal pour bénéficier de la méthode toString (Java)/__str__ (Python) de la classe Complexe qui est également héritée dans la classe Complexe2.
Indice
N’oubliez pas de déclarer un constructeur dans la classe Complexe2 qui appelle celui de Complexe. En effet, comme le constructeur de la classe Complexe attend deux paramètres (la partie réelle et la partie imaginaire du nombre complexe), il est important de l’appeler pour lui transmettre ces deux paramètres. Le constructeur de la classe Complexe2 nécessite, par conséquent, les mêmes...
Énoncé 6.7 : Les comptes en banque
Durée estimative : 30 minutes
Le but de l’exercice est d’écrire en Java/Python deux classes concrètes représentant des comptes bancaires : CompteClassique et CompteAvecDecouvert. La première classe représente des comptes de dépôt sans autorisation de découvert, leur solde est toujours positif ou nul. La seconde classe représente des comptes bancaires avec un découvert maximal autorisé préalablement fixé.
Pour simplifier le problème, nous proposons d’écrire une classe abstraite Compte qui possède l’attribut solde, la méthode ajoute pour ajouter un montant et qui introduit le retrait d’argent en tant que méthode abstraite retire. Cette méthode retire renvoie un booléen qui vaut vrai si le retrait a pu être effectué et faux dans le cas contraire. Créez également une méthode getSolde (Java)/get_solde (Python) qui retourne la valeur du solde.
Écrivez la classe abstraite Compte et les deux classes concrètes CompteClassique et CompteAvecDecouvert. Dans la classe CompteClassique, la méthode retire est écrite de sorte que le montant du retrait ne dépasse pas le solde disponible, faute de que quoi le retrait est refusé. Dans la classe CompteAvecDecouvert, la méthode...
Énoncé 6.8 : Les ensembles
Durée estimative : 25 minutes
Dans les exercices 4.10 et 4.11, nous avons écrit respectivement les classes Ensemble et EnsembleTrie. Ces deux classes respectent la même interface.
Il est demandé en Java d’écrire une interface appelée InterfaceEnsemble que chacune de ces classes va mettre en œuvre.
En Python, l’exercice consiste à définir l’interface commune par une surclasse abstraite InterfaceEnsemble qui sera héritée par chaque classe d’ensemble.
Reprenez ensuite le programme principal de test des exercices 4.10 et 4.11. Ce programme commence par demander à l’utilisateur s’il préfère travailler avec un ensemble trié ou non.
Énoncé 6.9 : Les portes logiques
Durée estimative : 30 minutes
Le but de l’exercice est d’écrire un ensemble de classes représentant des portes logiques. Les opérations communes à toutes les portes sont spécifiées en Java par l’interface Porte suivante :
public interface Porte {
void setEntree1(boolean valeur);
void setEntree2(boolean valeur);
boolean getEntree1();
boolean getEntree2();
boolean getSortie();
}
En Python, la spécification des opérations communes à toutes les portes est obtenue par la classe abstraite Porte suivante :
from abc import ABC, abstractmethod
class Porte(ABC):
@abstractmethod
def set_entree1(self, valeur: bool) -> None:
pass
@abstractmethod
def set_entree2(self, valeur: bool) -> None:
pass
@abstractmethod
def get_entree1(self) -> bool:
pass
@abstractmethod
def get_entree2(self) -> bool:
pass
@abstractmethod
def get_sortie(self) -> bool: ...