• Aucun résultat trouvé

Partie 2 : Bases de la POO

N/A
N/A
Protected

Academic year: 2022

Partager "Partie 2 : Bases de la POO"

Copied!
24
0
0

Texte intégral

(1)

Partie 2 : Bases de la POO

Prérequis : Comprendre et savoir appliquer les notions présentées dans la partie 1.

Objectif : Savoir distinguer les notions d’héritage et de composition et discerner leurs champs d’application respectifs. Etre capable de concevoir et d’implanter une hiérarchie de classes. Maîtriser les règles d’implantation et d’exécution des constructeurs dans un contexte d’héritage. Comprendre ce qu’est une méthode redéfinie et une méthode surchargée, maîtriser l’implantation de telles méthodes, être capable d’en simuler l’exécution. Maîtriser la gestion des exceptions, être capable d’implanter des exceptions, des méthodes qui lèvent et des méthodes qui interceptent des exceptions. Maîtriser l’utilisation de la classe ArrayList<T> et des classes enveloppes.

Par Olivier Bailleux, maître de conférences HDR en informatique.

[email protected]

Version de septembre 2017.

(2)

Introduction : un premier programme

On appelle classe dérivée d’une classe S toute classe D qui hérite de S dans le sens suivant :

• Toutes les variables de S appartiennent implicitement à D, mais peuvent être redéfinies dans S.

• Toutes les méthodes de S appartiennent à D, mais peuvent être redéfinies dans D.

• D peut posséder des variables d’instance, de classe, des méthodes d’instance, de classe, spécifiques quin’appartiennentpas à S.

Bienvenue dans cette deuxième partie du cours.

Il est temps d’aborder une notion essentielle en POO : l’héritage

Nous allons découvrir ces notions avec un exemple qui commence par la définition d’une classe Personne, qui représente un individu, et d’une classe Document, qui représente un document ayant un nom et un ou plusieurs auteurs (qui sont des instances dePersonne).

Pour l’instant il n’y a pas d’héritage, mais seulement un lien de composition entreDocumentetPersonne.

public class Personne {

private String nom;

private Date dateNaiss;

public Personne(String nom) {

this.nom=nom;

}

public Personne(String nom, Date naiss) {

this(nom);

this.dateNaiss = naiss;

}

public String toString() {

String s = nom;

if(dateNaiss!=null) {

s = s + "né le " + dateNaiss;

}

return s;

} }

Par défaut, dateNaiss est initialisée à null.

Appel du premier constructeur

(3)

Introduction : un premier programme

public class Document {

private String nom;

private Personne[] auteurs;

public Document(String n, Personne[] a) {

this.nom=n; auteurs = a;

}

public int nbAuteurs() {

return auteurs.length;

}

public String toString() {

String da;

if(nbAuteurs()==0) da="inconnu";

else {

da="";

for (int i = 0; i < nbAuteurs(); i++) da = da + auteurs[i] + " ";

}

return nom + "\nAuteur(s) : "+da;

} }

Les auteurs sont placés dans un tableau d’instances de Personne.

Retourne le nombre d’auteurs.

C V V

M M M

Personne V

M C V M M

Document

Lien de composition.

Les deux classes peuvent être représentées par ce schéma appelé diagramme de classes.

(4)

Introduction : un premier programme

La notion de composition correspond à l’auxiliaire avoir : un document a un ou plusieurs auteurs. A présent nous allons introduire une classe Livre qui représente uncas particulierde document : un livre estun document.

Cet auxiliaireêtretraduit la notiond’héritage.

public class Livre extends Document {

private long isbn;

private int annee;

public Livre(String nom, Personne[] aut, long isbn, int apub) {

super(nom, aut);

this.isbn=isbn;

annee=apub;

}

public long getIsbn() {

return isbn;

}

public String toString() {

String s = "Livre : "+super.toString();

return s+"\nISBN : "+isbn+" ("+annee+")";

} }

Le mot-clé extends traduit l’héritage. La classe Livre est dérivée de Document. Document est la superclasse de Livre.

Ces variables d’instance son spécifiques à la classe Livre.

Cette méthode d’instance est spécifique à la classe Livre.

Ceci est un constructeur de la classe Livre.

Le code de tout constructeur de la classe dérivée doit commencer par l’appel d’un constructeur de sa superclasse. Si le constructeur appelé est implicite alors on peut soit ne rien écrire, soit écrire super().

S’il est explicite (avec paramètre(s)) alors il faut écrire super(paramètre(s)).

Cette méthode existe déjà dans la superclasse et elle est ici redéfinie. La méthode toString de la superclasse est appelée depuis la classe dérivée grâce à la syntaxe super.toString().

(5)

Introduction : un premier programme

C V V

M M M

Personne

V

M C V M M

Document

Lien d’héritage.

Livre C

V V M M M

Voici le nouveau diagramme de classes incluant la classeLivre.

Toute instance de Livre estune instance de Document. Toute instance de Document a des auteurs qui sont des instances de Personne. Donc, évidemment, toute instance deLivreades auteurs…

(6)

Héritage et constructeurs

Il y a quelques règles à connaitre en matière d’héritage et de constructeurs :

Si une classe n’a pas de constructeur explicite alors Java lui ajoute un constructeur implicite qui

a) appelle leconstructeur par défautde sa superclasse, et b) initialise ses variablesd’instance avec desvaleurs par défaut.

Si une classe a au moins un constructeur explicite alors Java ne produit pas de constructeur par défaut implicite pour cette classe, mais on peut bien sûr lui donner unconstructeur par défaut explicite.

Si le code d’un constructeur explicite d’une classe dérivée ne commence pas par super(…) alors ce constructeur appelle implicitement le constructeur par défaut de sa superclasse. Et si la superclasse n’a pas de constructeur par défaut, le programme ne compile pas !

Si le code d’un constructeur explicite d’une classe dérivée appelle explicitement un constructeur de sa superclasse, son code doit commencer parsuper(…).

1

2

3

4

Je sais, c’est un peu indigeste, mais quand on comprend ces règle, on constate qu’elles sont pertinentes. Bien sûr, tout le monde se rappelle ce que signifieimpliciteet pardéfaut?

He bien à vrai dire…

implicite : produit automatiquement pas le compilateur, non visible dans le code.

explicite : écrit par le programmeur.

constructeur par défaut: sans paramètres.

valeur par défaut : placée automatiquement dans une variable quin’estpas initialisée explicitement.

(7)

Héritage et types

En Java, chaque variable et chaque paramètre a un type. Nous avons vu qu’il existe des types primitifs : int, boolean, double, long. Chaque nom de classe représente aussi un type. Mais du fait del’héritage,une instance de classe peut avoir plusieurs types!

Voici un premier exempled’utilisation de notre classeLivre.

Livre w = new Livre(

"Patience dans l'azur",

new Personne[]{new Personne("Hubert Reeves")}, 2020099179,

1981);

System.out.println(w.toString());

System.out.println(w.getIsbn());

Qui produitl’affichage:

Livre : Patience dans l'azur Auteur(s) : Hubert Reeves ISBN : 2020099179 (1981) 2020099179

Maintenant, il est aussi possibled’écrire: Document w = new Livre(

"Patience dans l'azur",

new Personne[]{new Personne("Hubert Reeves")}, 2020099179,

1981);

System.out.println(w.toString());

Car toute instance de Livre est aussi par héritage une instance de Document. Mais…Iln’estplus possibled’appelerla méthodegetIsbn.

System.out.println(w.getIsbn()); Ne compile pas !

Parce que c’estune méthode deLivre quin’existe pas dansDocument, et que la variable w est de type Document. Pas de problème avec la méthode toString qui est redéfinie dans la classe Livre mais existe dans Document et,cerise sur le gâteau, c’est la méthode toString de Livrequi sera exécutée et non celle deDocument.

Ce petit miracle s’appelle laliaison dynamique et nous y reviendrons plus tard.

(8)

Héritage et représentation en mémoire

Voici ce qui se produit dans la mémoire lors de l’exécution des lignes suivantes située dans une méthodetest.

w

PILE

TAS

instance de Livre

variable de test

nom dateNaiss null

représentation simplifiée d ’une instance de String

"Patience dans l’azur"

isbn 2020099179

annee 1981 nom auteurs

"Hubert Reeves"

Livre w = new Livre(

"Patience dans l'azur",

new Personne[]{new Personne("Hubert Reeves")}, 2020099179,

1981);

variables

d’instance héritées de Document

tableau d’instances de Personne de taille 1

instance de Personne

(9)

Compléments sur l’héritage et la structuration des programmes

Package. Un package regroupe un ensemble de classes. Le fichier dans lequel est définie une classe d’un package p doit comporter, au début, la

déclaration : L’élémentest accessible depuis toutes les classes du programmes.

public

Droits d’accès. Jusqu’à maintenant, nous avons utilisé deux droits d’accès : public et private. Il en existe deux autres : protected et « par défaut ». Ce dernier s’appliquelorsque le droit d’accèsà un élémentn’est pas précisé.

package p;

Si une classe C utilise une classe Usituée dans un package q différent de celui où elle se trouve, une des déclarations suivantes doit apparaître avant la définition deC:

import q.U; import q.*;

Les classes ont elles-mêmes des droits d’accès. Une classe directement définie dans un fichier sources .java, comme nous l’avons fait jusqu’à présent, peut avoir le droitpublic ou « par défaut ». Une classepublicest utilisable danstout le programmeoù elle est définie, une classe avec droit d’accès par défaut n’est utilisable que depuis le package où elle est définie.

Droits d’accèsdes méthodes et variables de classe etd’instance.

L’élément est accessible seulement depuis la classe où il est définit ou déclaré.

private

L’élément est accessible depuis les classes dérivées de la classe où il est défini et déclaré et depuis toutes les classes du même package.

protected

L’élément est accessible seulement depuis les classes du package de la classe où il est définit ou déclaré.

par défaut

définit ou déclaré ?

On définitune méthode, mais on déclareune variable.

importe toutes les classes du package

(10)

Compléments sur l’héritage et la structuration des programmes

Hiérarchie de classes. Une classe déclarée final ne peut avoir de classe dérivée. Mais en dehors de cette restriction, toute classe dérivée peut elle-même avoir des classes dérivées. D’ailleurs toutes les classes descendentd’une classe définie par Java nomméeObject. Par contre Java ne permet pas l’héritage multiple : chaque classe (excepté Object) a une seule superclasse.

Document

Livre Vidéo

Roman ManuelScolaire Object

Exemple de hiérarchie de classes

Or il se trouve que la classe Object possède nativement certaines méthodes, dont notamment la méthode toString. On peut donc utiliser cette méthode héritée depuis n’importe quelle classe, même si elle n’y est pas redéfinie.

Pas d’héritage multiple, c’est dommage non ?

Mais elle retourne quoi, cette méthode toStringhéritée ?

C’est en partie compensé par la notion d’interface, que nous verrons plus tard.

La méthode toStringde la classe Objectaffiche l’adresse mémoire de l’instance courante.

(11)

La classe ArrayList<T>

Notion de classe générique. Une classe C peut admettre un ou plusieurs paramètres qui devront être remplacés par des noms de classe au moment de créer des instances de C. Par exemple, la classe ArrayList<T>

est paramétrée par une classe T.

La classeArrayList<T> représente une liste de référencesd’instances de T.

Une telle liste est plus souple d’utilisation qu’un tableau car sa capacité n’est pas limitée (du moins elle n’est limitée que par les ressources mémoire).

Examinons un exemple. Je veux créer une liste de dates (techniquement, d’instancesde la classeDate).J’écrissimplement :

ArrayList<Date> t = new ArrayList<>();

Une liste vide est créée dans le tas et sa référence est placée dans w.

Cette liste à une capacité initiale de 10 emplacements, mais cette capacité sera automatiquement augmentée si on y place plus de 10 éléments.

J’ajoutedeux dates à ma liste.

t.add(new Date(1,1,1901));

t.add(new Date(2,2,1902));

t

jour 1 1 1901 mois

annee

Représentation stylisée d’une instance d’ArrayList

jour 2 2 1902 mois

annee

instance de Date

Puis je chausse mes lunettes à regarder dans la mémoire. Oups, je les avais déjà sur le nez.

C’est donc ça votre secret !

(12)

La classe ArrayList<T>

L’essentielà savoir concernant la classeArrayList<T>,c’estque :

• toute instancewcontientt.size()éléments,

• tout élément est soit une référence de type T, soitnull.

• la position de chaque élément est désignée par un indice,

• le premier élément a pour indice 0.

int size() : retourne le nombre d’éléments stockés

Voici quelques méthodes de la classe ArrayList. Il y en a beaucoup d’autres, que vous pourrez trouver dans la documentation officielle à l’URLhttps://docs.oracle.com/javase/8/docs/api/

int add(T e) : ajoute l’élément e en fin de liste

int add(int i, T e) : ajoute l’élément e en position i et décale (si applicable) les éléments suivants d’une position. La plus grande valeur autorisée pour i est size().

T get(int i, T e) : retourne l’élément situé en position i. La plus grande valeur autorisée pour i est size()-1.

T remove(int i) : retire l’élément situé en position i et le retourne.

Les éléments suivants (si applicable) sont décalés d’une position pour boucher le « trou ».

Ne me dites pas qu’une documentation en anglais vous fait peur...

Non non non...

T clear(int i) : retire tous les éléments de la liste.

T set(int i, T e) : remplacel’élément situé en position i par e T indexOf(Object e) : retourne l’indice de la position de la première occurrence de l’objet e dans la liste, ou -1 si cet objetn’estpas dans la liste. (Toute référence a le typeObjectpar héritage.)

(13)

La classe ArrayList<T>

Voici une nouvelle version de la classe Document dans laquelle les auteurs sont stockés dans une ArrayList au lieu d’un tableau. Cette variante peut remplacer la précédente sans changement dans le code, parce-que les méthodes public ont les mêmes signatures, c’est à dire les mêmes nombre et types des paramètres et les mêmes valeurs de retour.

public class Document {

private String nom;

private ArrayList<Personne> auteurs;

public Document(String n, Personne[] a) {

this.nom=n;

auteurs = new ArrayList<Personne>();

for(int i=0; i<a.length; i++) {

auteurs.add(a[i]);

} }

public int nbAuteurs() {

return auteurs.size();

}

public String toString() {

String da = "";

for (int i = 0; i < nbAuteurs(); i++) {

da = da + auteurs.get(i) + " ";

}

return nom + "\nAuteur(s) : "+da;

} }

Les éléments du tableau a sont ajouté un à un à la liste auteurs.

Il existe un moyen plus rapide, mais nous n’avons pas encore les bases pour le comprendre.

La méthode toString a été un peu simplifiée pour faciliter la mise en page. Elle utilise la méthode

ArrayList.get pour récupérer les noms des auteurs.

Variable d’instance destinée à contenir la référence d’une instance de ArrayList<Personne>.

C’est pour ça que le constructeur prend toujours un tableau en

paramètre ?

Oui. Mais on pourrait ajouter un autre constructeur prenant un

ArrayListen paramètre.

(14)

Les classes enveloppes

En java, les types primitifs ne sont pas des objets. Ils constituent une sorte d’entorse au paradigme de programmation objet. Mais il existe des classes enveloppes qui permettent d’encapsuler des données de types primitifs dans des objets :Integer,Double,Boolean...

Peut-on mettre des entiers ou autres types primitifs dans une ArrayList ?

Non. Mais on peut utiliser des classes enveloppes!

ArrayList<Integer> liste = new ArrayList<>();

liste.add(new Integer(15));

liste.add(33);

int val = liste.get(1);

System.out.println(liste);

liste d’instances de Integer contenant chacune un entier

ajout d’un nouvel élément

idem avec notation simplifiée autorisée par java

conversion implicite en int de l’instance de Integer lue dans la liste

liste

15

instance d’ArrayList<Integer>

instance de Integer

33

(15)

Les exceptions

Jusqu’à maintenant, nous avions deux moyens pour transmettre des informations à une méthode et récupérer des informations fournies par cette méthode : (1) les paramètres et la valeur de retour, et (2) les effets de bords (modification d’une variable d’instance, voir de classe par la méthode).

int faireCeci(int a, int b) {

this.cpt = this.cpt+1;

return(...) }

Information sortante

Informations entrantes

Informations entrantes et sortantes par effets de bord

Or il existe un troisième moyen, pour une méthode, de recevoir et de produire des informations :les exceptions. Une exception est unobjetqui contenir des informations, être produit par une méthode, en sortir, rentrer dans une autre méthode, y êtreinterceptéou en ressortir.

Nous allons voir sur un exemple comment fonctionne ce système d’exceptions.

Nous allons illustrer le concept d’exception avec une classe Simu permettant de simuler une marche aléatoire d’un mobile se déplaçant en ligne droite. Notre mobile a une position initiale et se déplace par étapes vers un objectif situé à une certaine distance dist de cette position initiale. A chaque étape, avec une probabilité ½, soit il avance vers l’objectif d’une distance dAv, soit il s’en éloigne d’une distance dAr. On souhaite connaitre le nombre d’étapes nécessaires, en moyenne, pour atteindre l’objectif.

départ dist arrivée

dAr dAv

Notre classeSimupossède 4 variablesd’instanceet une variable de classe qui représente le nombre maximum de déplacements autorisés pour chaque simulation.

public class Simu {

private double dist, pos, dAv, dAr;

private static final int nmaxDepl=1000;

// A compléter }

(16)

Les exceptions

Le constructeur de Simu initialise à 0.0 la variable d’instance pos et initialise les autres variables d’instance avec les valeurs qui lui sont passées en paramètres.

La méthode simul réalise un suite de déplacements jusqu’à ce que la distance à parcourir soit atteinte. Elle retourne le nombre de déplacements qui ont été nécessaires. Elle lève une exception de type Timeoutsi le nombre maximum de déplacements autorisés est atteint.

public Simu(double dist, double dAv, double dAr) {

this.dist=dist; this.pos=0.0;

this.dAv=dAv; this.dAr=dAr;

}

méthode deplace effectue un mouvement en appliquant la règle de déplacement.

void deplace() {

if(Math.random()<0.5) {

pos = pos-dAr;

if(pos<0.0) pos=0.0;

} else {

pos=pos+dAv;

} }

int simul() throws Timeout {

int n=0; this.pos=0.0;

while(pos<dist) {

if(n>nmaxDepl) {

throw new Timeout(n);

}

n++; deplace();

}

return n;

}

Ceci indique qu’une exception de type Timeout peut « sortir » de la méthode simul.

L’instruction throw lève (produit) une exception de type Timeout. Cette exception est un objet créé par un constructeur de la classe Timeout.

(17)

public class Timeout extends Exception {

private int nDepl;

public Timeout(int n) {

nDepl=n;

}

public String toString() {

return "Objectif non atteint apres "+nDepl+

"deplacements.\n";

} }

Les exceptions

Notre classe d’exception Timeout a une variable d’instance nDepl, initialisée par son constructeur au moment de la création d’une exception. Cette variable d’instancecontient le nombre de déplacements ayant été réalisé au moment oùl’exception est produite.

Elle hérite de la classe prédéfinie Exception, qui possède une variable d’instance de type String pouvant contenir un message et une méthode toString qui affiche ce message. Mais nous n’utilisons pas ces éléments dans notre implantation.

Les classes d’exceptions de Java doivent descendre de la classe prédéfinie Exception.

C’est ainsi que Java peut savoir que ce sont des classes permettant de produire des exceptions.

STOP ! D’où sort cette classe Timeout?

C’est une classe d’exceptions que nous allons définir nous même,

mais il en existe qui sont déjà toutes faites.

Ce constructeur sera utilisé pour lever une exception de type Timeout.

Cette méthode pourra être utilisée pour obtenir des informations sur la cause de l’exception.

(18)

Les exceptions

A présent nous allons définir une méthode stat qui réalise plusieurs simulations afin de calculer une moyenne du nombre de déplacements nécessaires pour parcourir la distance de référence contenue dans la variabled’instancedist.

Comme la méthode stat appelle la méthode simul qui peut lever une exception, elle est obligée de dire que qu’elle fait dans le cas où l’exceptionserait produite. Et il y a deux choix possibles :

double stat(int nExp) throws Timeout {

double sum=0.0;

for(int i=0; i<nExp; i++) {

sum = sum + simul();

}

return sum/nExp;

}

Dans notre cas, la méthode stat n’intercepte pas l’exception mais « refile la patate chaude » à la méthode qui a appelé stat. En quelque sorte, l’exceptionne fait que « traverser »stat.

Soit elleintercepte l’exception. Soit elle la faitremonter.

Ceci signifie que si une exception de type Timeout arrive (et n’est pas interceptée) pendant l’exécution de stat, cette exception ne sera pas traitée dans cette méthode mais

« remontée » à la méthode qui a appelé stat.

L’exécution de la méthode simul peut produire une exception de type Timeout. Le compilateur exige de savoir ce qu’il faut en faire.

Attendez voir, l’exception va être «remontée » à la méthode appelante, mais si cette méthode la « remonte »

à sa méthode appelante etc., se peut-il que l’exception ne soit jamais traitée ?

L’exception finira par arriver dans la méthode main. Si elle-même la « remonte », cela

produira l’arrêt du programme.

(19)

public static void test() {

Simu sim = new Simu(10.0,1.0,1.0);

try {

System.out.println(sim.stat(100));

}

catch(Timeout e) {

System.out.println(e);

}

System.out.println("ok");

}

Les exceptions

La méthode stat est elle-même appelée par une méthode test, qui peut donc voir arriver une exception de type Timeout qui remonte de stat.

Mais cette fois, nous avons choisid’intercepter cette exception (si elle se produit).

On place ici les lignes de codes pouvant produire une exception à intercepter.

Cette interception se fait àl’aidedel’instruction try catch. Dans notre cas, une seule exception est interceptée, mais il est possible d’utiliser plusieurs clauses catch successives pour intercepter différent types d’exception et réaliser des traitements spécifiques à chaque cas. Il faut alors intercepter en premier les exceptions les plus spécifiques. Par exemple, un catch(Exception e) interceptera toutes les exceptions, parce que toutes les instances de classes d’exception héritent du type Exception.

Si une exception de type Timeout est produite, les lignes de code placées ici sont exécutées. La variable e désigne l’instance d’exception interceptée.

Qu’une exception ait été ou non interceptée, la suite du code est exécutée après l’exécution du code situé dans la clause try, sauf si l’exécution du code de la clause catch a provoqué l’arrêt d’exécution de la méthode. Si on veut que du code soit toujours exécuté, qu’une exception soit levée ou non, après la fin de l’exécution du code dans try, il faut ajouter une clause finally après les clauses catch.

Peut on lever une exceptions dansune clause catch?

Oui.

(20)

Les exceptions

Examinons ce qui se passe si on exécute la méthode test et qu’aucuneexception ne se produit.

valeurs des variables d’instance.

int simul() throws Timeout {

throw new Timeout(n);

return(…) }

double stat(int nExp) throws Timeout {

simul();

return(…);

} void test()

{

try {

… stat(100); … }

catch {

} }

La méthodetestappelle la méthodestatqui appelle la méthodesimulqui récupère des informations dans certaines variables d’instance et met à 0 la variable d’instance pos. La méthode simul transmet son résultat à sa méthode appelante stat par retour de valeur. La méthode stat fait de même avectest.

(21)

int simul() throws Timeout {

throw new Timeout(n);

return(…) }

Les exceptions

Maintenant, voyons ce qui se passe si une exception est levée par simul.

Lorsqu’une exception est levée dans une méthode (et qu’elle n’est pas immédiatement interceptée), elle interrompt l’exécution de cette méthode. Il n’y aura donc pas de valeur de retour. La méthode appelante reçoit une instance de la classe d’exception utilisée. Cette instance peut permettre de transmettre des informations.

valeurs des variables d’instance.

double stat(int nExp) throws Timeout {

simul();

return(…);

} void test()

{

try {

… stat(100); … }

catch( ) {

} }

représentation stylisée d’une exception de type Timeout.

(22)

Les exceptions

ArrayIndexOutOfBoundsException, comme d’autres exceptions pouvant se produire en cas de mauvaise utilisation de certaines opérations, comme par exemple une division entière par 0, sont dérivées de la classe prédéfinie RuntimeException. Il n’est pas obligatoire de les remonter explicitement, ni de les intercepter. Elles traduisent des erreurs de programmation. On peut les intercepter et les gérer avec try catch, mais sinon, comme elles ne sont pas censées se produire, elles sont implicitement remontées jusqu’à la méthode main, qui elle-même les remonte par défaut à la machine virtuelle, qui arrête le programme en indiquant dans quelle méthodel’erreur c’estproduite.

Nous avons dit que toute exception doit être soit interceptée, soit explicitement remontée, mais il y a une.. exception à cette règle.

Considérons la méthode suivante :

public static void testRunTimeExp() {

int[] tab = new int[10];

tab[10]=3;

}

Cette méthode tente d’écrire la valeur 3 dans une cellule du tableau qui n’existe pas, puisque les cellules d’un tableau de taille 10 sont numérotées de 0 à 9, ce qui provoque une interruption de type ArrayIndexOutOfBoundsException. Pourtant, Java n’a pas exigé que nous indiquions dans le code ce qu’il faut faire dans le cas où cette exception est levée. De fait, àl’exécution,on peut lire sur la console :

Exception in thread "main"

java.lang.ArrayIndexOutOfBoundsException: 10

at pool2.Tests.testRunTimeExp(Tests.java:39) at Main.main(Main.java:9)

Peut-on créer nos propres classes d’exception qui remontent toutes seules sans avoir besoin d’utiliser trowsoutry/catch?

Oui, en dérivant ces classes deRunTimeException, mais cette pratique devrait se limiter aux exceptions qui traduisent des erreurs de programmation.

(23)

Exercices d’assimilation

Exercice 1. Réalisez une classe Video qui représente un cas particulier de Document. Les instances de Video représentent des vidéos qui, en plus de tous les attributs d’undocument, ont une durée. Cette durée doit être l’un des paramètres du constructeur de la classe Video. La classe Video doit redéfinir la méthodetoStringde sorte que cette méthode retourne la description retournée par la méthode toString de Document, complétée avec la durée. La classe Video doit être dotée en outre d’une méthode getDuree qui retourne le durée de la vidéo représentée par l’instance courante.

Exercice 2.Réalisez une classeRoman qui représente un cas particulier de Livre. Les instances de Roman représentent des roman qui, en plus de tous les attributs d’un livre, ont un genre, représenté par une chaîne de caractère. Ce genre doit être l’un des paramètres du constructeur de la classe Roman. La classe Roman doit redéfinir la méthode toString de sorte que cette méthode retourne la description retournée par la méthodetoStringdeLivre, complétée avec le genre.

Exercice 3. Réalisez une classe Mediathequequi représente un site où il y a des documents. Cette classe comporte une variable d’instance de type ArrayList<Documents>. Son constructeur crée une médiathèque vide.

Une méthode ajoute permet d’ajouter un nouveau document. Une méthode nDocs retourne le nombre de documents. Une méthode Document getDoc (inti) retourne le document situé en position i dans la collection. Une méthode toString retourne comme il se doit une description du contenu del’instancecourante.

Exercice 4. Réalisez une méthode statique test, située dans une classe Main, qui crée une instance de Mediatheque, y ajoute quelques documents de votre choix, puis affiche les descriptions des documents n’ayant qu’un seul auteur.

Exercice 5. Modifiez les constructeurs de la classe Personnede manière à ce qu’ils lèvent une exception de type RuntimeException si le paramètre nomvautnull.

Exercice 6. Modifiez la méthode stat de la classe Simu de manière à ce qu’elle lève une exception DivZero si le paramètre nExp vaut 0. La classe DivZero devra être définie comme une clase dérivée de Exception possédant juste un constructeur par défaut qui appelle implicitement le constructeur par défaut deException.

Exercice 7. Modifiez la méthode test de la classe Simu de façon à ce qu’elle intercepte aussi les exceptions de type DivZero et affiche un message spécifique si une telle exception se produit.

Une division par 0 ne produit-elle pas de toutes façonsune exception?

Seulement la division entière. Avec des nombres flottants, le résultat est

une valeur normalisée notée NaN.

(24)

Exercices d’assimilation

Exercice 8.La méthode suivante permet de saisir un entier au clavier.

public static int lireInt() {

return new Scanner(System.in).nextInt();

}

Mais si la valeur saisie n’est pas un entier, elle produit une exception de type InputMismatchException. Proposez une nouvelle version de la méthode lireIntqui en cas de saisie correcte, retourne une instance de la classe enveloppe Integer contenant l’entier saisi, et qui dans le cas contraire retournenull.

Documentez-vous sur le concept d’énumération en Java et proposez une nouvelle version de la classe Date dont les jours et les mois sont représentés par des types énumérés.

Réalisez une fiche de synthèse sur ce sujet en expliquant l’intérêt des énumérations et la manière de les utiliser.

Exercice 9. Proposez une troisième version de la méthode lireInt de l’exerciceprécédent qui en cas de saisie correcte, retournel’entiersaisi (la valeur de retour est donc de type int, comme pour la première version), et qui, en cas de saisie incorrecte, redemande à l’utilisateur de faire une nouvelle saisie jusqu’àcequ’unesaisie correcte soit réalisée.

Exercice 10. Placez les lignes suivantes dans une méthode statique, exécutez-là et expliquez le résultat obtenu.

Date d1 = new Date(1,2,2003);

Date d2 = new Date(1,2,2003);

if(d1==d2)

System.out.print("Les dates sont identiques");

else

System.out.print("Les dates sont différentes");

Exploration

Mais avec tout ça, on

ne sait rien faire...

? ? ?

Il veut dire qu’on ne sait pas réaliser de « vraies » applications, avec des fenêtres, menus, lecture et

enregistrement de fichiers...

Ce cours introduit les concepts de la programmation objet et les applique

avec Java.

Pour créer des applications avec interfaces utilisateurs avancées, il vous faudra suivred’autres enseignements.

Références

Documents relatifs

d) Écrire dans la classe Segment une méthode toString permettant d’afficher les deux points d’un segment. On utilisera la méthode toString de Pixel selon la technique de

Le livre EST le problème ; le livre est tout le problème… ou plutôt l’industrialisation du livre et tout ce que, dès son origine, elle implique et qui, peu à peu, s’enchaîne

Sans doute, si certaines de ces traces sont authentiques, d'autres sont déformées (chroniques tendancieuses), mais clans leur déformation, elles portent ce- pendant

Une discussion sur l'année internationale de l'enfant nous a fait chercher quels étaient les droits que nous voudrio ns avoir ou que nous jugeons indispensables

avec le sq uels

Certaines pages ne portent que des nota tions très rapides valables pour moi seulement Je n' ai pas toujours le tenp:; de

Notez ce nom de fichier que vous associez à P1.EXT Avec de la chance vous n'aurez pas de 1.0 Error.. Rebobinez un peu si nécessaire et faites de même avec P2, P3,

On peut par exemple calculer la somme des b n (et l’implémenter à l’aide d’une boucle for) mais le plus simple est de calculer la différence entre le capital emprunté et le