Objectif: L’objectif de ce TP est de découvrir les bases de la programmation orientée objet avec Java. Nous nous attacherons à construire et à manipuler une classe très simple pour mettre en pratique les notions de classe, d’objet, d’attribut, de méthode, de rétention d’information (encapsulation en anglais), de constructeur, ...
La première partie de ce sujet (Nombres Rationnels) est une reprise d'un sujet donné dans le cours de Programmation Orientée Objet en 2ème année ENISMAG (le sujet original).
Vous connaissez probablement tous la définition de l’ensemble \(\mathbb{Q}\) des rationnels. Un nombre rationnel est un nombre qui peut être défini par un ratio \(n/d\) , où \(n\), appelé numérateur, est un entier relatif, et \(d\), appelé dénominateur, est un entier relatif non nul. Nous allons dans ce TP construire une classe représentant les nombres rationnels.
Avant tout chose organisez votre espace disque afin de pouvoir par la suite retrouver facilement le travail effectué lors de cette séance de TP. Pour cela, dans le répertoire PLAI/Java créé lors du TP1, ajoutez un sous répertoire TP04 dans lequel vous rangerez le travail effectué au cours ce TP.
1ère Partie : Nombres Rationnels
Première version d’une classe Rational
Commençons doucement en créant une première version très simple d'une classe
Rational
qui
représente un nombre rationnel.
- Créez une classe
Rational
, possédant deux attributs entiers \(num\) et \(denom\) . (Reportez vous au TP 03 pour voir comment créer un projet Java et une classe avec l'IDE VSCode). - Écrivez un programme de test qui crée une fraction \(3/2\), affiche son numérateur, et affiche son dénominateur (dans la console).
- Compilez et exécutez ce programme pour vérifier que votre classe
Rational
fonctionne correctement.
Représentation textuelle d’un rationnel
-
Modifiez votre classe
Rational
afin d’y ajouter une méthodetoString()
sans paramètre, et renvoyant une chaîne de caractères (type String) représentant le nombre rationnel (par exemple, cette méthode, appelée sur le rationnel \(3/2\), devrait renvoyer la chaîne de caractères "3 / 2"). -
Modifiez votre programme de test pour utiliser la méthode
toString()
créée précédemment. Compilez et exécutez.
Exceptions
-
Modifiez votre programme de test pour créer un autre rationnel de dénominateur égal à 0. Est-ce possible ? Si oui, en quoi est-ce un problème ?
-
Pour empêcher la création et la manipulation d’objets rationnels ayant pour dénominateur 0. Vous ajouterez au constructeur de votre classe
Rational
un test qui au cas où le dénominateur serait nul exécute l'instruction suivante :throw new IllegalArgumentException("Dénominateur nul");
Modifiez votre programme de test pour créer un rationnel avec un dénominateur nul, que ce passe-til ? D'après vous quel est le rôle et l'effet de l'instruction précédente ?
Opérations arithmétiques
Pour rappel (au cas où...), la multiplication de deux rationnels est définie de la manière suivante : \begin{equation} \frac{n}{d} \times \frac{n'}{d'} = \frac{nn'}{dd'} \end{equation}
-
Ajoutez à votre classe
Rational
une méthodemult
prenant en paramètre un autre rationnel, et le multipliant au rationnel sur lequel elle est appliquée. La méthode ne renvoie rien (type de retourvoid
).Cette opération modifie l’état de l’objet sur lequel la méthode est invoquée :
a.mult(b)
revient à faire \(a \leftarrow a*b\). Il n’est pas possible en Java de redéfinir des opérateurs (comme en C++), sinon ce serait équivalent à \(a *= b\). -
Modifiez votre programme de test en créant un second rationnel (\(1/3\) par exemple), en le multipliant au premier, et en affichant le résultat. Compilez et exécutez.
-
Mêmes questions pour l’addition. Pour rappel, l’addition de deux rationnels est définie de la manière suivante : $$ \frac{n}{d}\ + \frac{n'}{d'} = \frac{nd' + n'd}{dd'}$$
Fractions irréductibles
En plus d’interdire la création et la manipulation de rationnels dont le dénominateur
est à \(0\), nous souhaitons que tout rationnel soit toujours sous sa forme irréductible. Il
s’agit d’un
invariant de classe : à tout instant, et ce dès sa création, un objet Rational
est
toujours sous forme
irréductible.
Pour rappel, un rationnel \(n/d\) est sous forme irréductible si et seulement si \(pgcd(n, d) = 1\), avec :
fonction pgcd(a,b) si b est égal à 0 renvoyer a sinon renvoyer pgcd(b, reste(a,b))
Par exemple, la forme irréductible du rationnel \(8/12\) est \(2/3\). avec :
-
Modifiez votre classe
Rational
en conséquence. Testez. -
Ecrivez une fonction qui teste l'égalité de deux nombres rationnels. Testez.
2ème Partie : Séquence d'entiers
Il s'agit ici d'écrire en Java une implémentation d'un type abstrait séquence d'entiers.
Les opérations possibles sur une séquence sont les suivantes :
Créer une séquence vide
-
Ajouter une nouvelle valeur en tête de séquence
-
Ajouter une nouvelle valeur en fin de séquence
-
Obtenir la longueur de la séquence (le nombre de valeurs présentes)
-
Tester si la sequence est vide
-
Récupérer la valeur (entier) d'un élément de la séquence désigné par son rang (entier compris en tre 1 et la longueur de la séquence
-
Retirer le premier élément de la séquence.
-
Retirer le dernier élément de la séquence
-
Rechercher le rang d'une valeur donnée dans la séquence. Cette fonction retourne un entier qui correspond au rang de la première occurence de la valeur dans la séquence en partant du début de celle-ci. Si la valeur n'est pas présente la valeur retournée est -1.
-
Rechercher le rang d'une valeur donnée dans la séquence à partir d'un rang donné. Cette fonction retourne un entier qui correspond au rang de la première occurence de la valeur dans la séquence en partant du rang donné. Si la valeur n'est pas présente la valeur retournée est -1.
Question 1: Ecrivez le code d'une classe SequenceEntiers qui impélémente ce type abstrait à l'aide d'une liste chaînée et un programme permettant de la tester.
Indication : Pour la réalisation de SequenceEntiers, écrivez une deuxième classe ElementSeqEntierqui permet de représenter un élément de la séquence (une valeur entière et un pointeur (une référence) sur l'élement suivant).
Question 2: Rajouter à votre classe SequenceEntiers un deuxième constructeur qui permet de créer une séquence en faisant la copie d'une séquence passée en paramètre.
Ecrivez un programme de test de ce constructeur.
Question 3: Rajoutez à votre classe SequenceEntiers une méthode qui permet d'obtenir une nouvelle séquence ne contenant que les valeurs de rang impairs dans la séquence.
Ecrivez un programme de test de cette méthode.