Programmation 2014 2015-1

199
8/10/2019 Programmation 2014 2015-1 http://slidepdf.com/reader/full/programmation-2014-2015-1 1/199 P r o g r a m m a t i o n UV Bases de la programmation A1S1 2014-2015 [email protected] - B227 - Ecole des Mines de Nantes - - 1 - 

Transcript of Programmation 2014 2015-1

Page 1: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 1/199

P r o g r a m m a t i o nUV Bases de la programmation A1S1 2014-2015 [email protected] - B227

- Ecole des Mines de Nantes  -

- 1  - 

Page 2: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 2/199

 

Page 3: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 3/199

 

1. Sommaire

2.  Introduction ...................................................................................................................................... 5 

2.1. 

Zoom sur

 l’ordinateur

 ..................................................................................................................................

 5 2.1.1.  Le matériel ...........................................................................................................................................................  5 

2.1.2.  Le logiciel ..............................................................................................................................................................  6 

2.2.  Les langages de programmation ..................................................................................................................  6 

2.3.  Les phases du développement .....................................................................................................................  7 

2.3.1.  La phase de spécification .....................................................................................................................................  7 

2.3.2.  La phase de modélisation et de découpage .........................................................................................................  8 

2.3.3.  La phase d’analyse ...............................................................................................................................................  8 

2.3.4.  La phase de conception ........................................................................................................................................  8 

2.3.5.  L’implémentation .................................................................................................................................................  9 

2.3.6.  La compilation ......................................................................................................................................................  9 

2.3.7.  Débogage .............................................................................................................................................................  9 

2.4.  Conventions d’écriture ..............................................................................................................................  10 

2.5.  Les outils ....................................................................................................................................................  10 

2.5.1.  Installation du Kit de Développement Java (JDK) ...............................................................................................  10 

2.5.2.  Installation d’Eclipse ..........................................................................................................................................  11 

2.5.3.  Lancer Eclipse depuis un ordinateur de l’EMN ...................................................................................................  12 

3.  Les concepts de programmation ..................................................................................................... 15 

3.1.  Un programme minimaliste .......................................................................................................................  15 

3.2.  Commentaires ............................................................................................................................................  18 

3.3.  Des données et des méthodes ...................................................................................................................  18 

3.4.  Classe .........................................................................................................................................................  20 

3.4.1. 

Nom d’une

 classe

 ...............................................................................................................................................

 20

 3.4.2.  Déclaration d’une classe ....................................................................................................................................  20 

3.4.3.  Variables d’instance ...........................................................................................................................................  21 

3.5.  Premier objet .............................................................................................................................................  24 

3.5.1.  Variables locales et affectation ..........................................................................................................................  25 

3.6.  Méthodes d’instance .................................................................................................................................  29 

3.7.  La classe String ......................................................................................................................................  35 

3.8.  Conversions implicites et explicites ...........................................................................................................  38 

3.8.1.  Conversion implicite / promotion ......................................................................................................................  38 

3.8.2.  toString() ............................................................................................................................................................  39 

3.8.3.  Conversion explicite / Casting / Coercition / Transtypage .................................................................................  39 

3.8.4. 

Conversion des

 chaînes

 de

 caractères

 ...............................................................................................................

 39

 3.9.  Entrées / Sorties .........................................................................................................................................  41 

3.9.1.  Afficher ...............................................................................................................................................................  41 

3.9.2.  Effectuer une saisie au clavier ............................................................................................................................  41 

3.10.  Egalité ........................................................................................................................................................  43 

3.11.  L’alternative / Conditionnelle simple .........................................................................................................  45 

3.12.  Visibilité/Accessibilité et encapsulation .....................................................................................................  48 

3.12.1.  Niveaux de visibilité ...........................................................................................................................................  48 

3.12.2.  Des méthodes rarement private ........................................................................................................................  49 

3.12.3.  L’encapsulation ..................................................................................................................................................  50 

3.12.4.  S’affranchir autant que possible de la représentation mémoire .......................................................................  51 

3.12.5. 

 javadoc ...............................................................................................................................................................

 52

 3.13.  Association, Agrégation et Délégation .......................................................................................................  54 

Page 4: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 4/199

 

Introduction  Programmation Zoom sur l’ordinateur  [email protected] – B227 

3.13.1.  Agrégation et délégation ...................................................................................................................................  54 

3.13.2.  Association .........................................................................................................................................................  54 

3.13.3.  Pseudo diagramme de classe .............................................................................................................................  55 

3.14.  Retour sur les constructeurs ......................................................................................................................  57 

3.14.1.  Recopie profonde / superficielle........................................................................................................................  57 

3.14.2. 

Chaînage de

 constructeurs

 ................................................................................................................................

 59

 

3.15.  Les tableaux ...............................................................................................................................................  60 

3.16.  Les boucles while ....................................................................................................................................  64 

3.17.  Méthodes de classe (static) ..................................................................................................................  70 

3.18.  Decomposer ...............................................................................................................................................  71 

3.19.  Utiliser des constantes ...............................................................................................................................  72 

3.20.  Les boucles do…while .............................................................................................................................  73 

3.21.  Incrémentations et affectations ................................................................................................................  74 

3.22.  Les boucles for .........................................................................................................................................  75 

3.23.  Les branchements / choix multiples switch ...........................................................................................  78 

3.24. 

Les exceptions

 ............................................................................................................................................

 81

 3.24.1.  Réagir face à une exception ...............................................................................................................................  81 

3.24.2.  Lever une exception ..........................................................................................................................................  82 

3.25.  Les fichiers texte séquentiels .....................................................................................................................  83 

3.25.1.  Ecrire dans un fichier texte ................................................................................................................................  83 

3.25.2.  Lire un fichier texte ............................................................................................................................................  84 

3.26.  Les interfaces .............................................................................................................................................  85 

3.26.1.  Des types de données abstrait ...........................................................................................................................  85 

3.26.2.  Des contrats .......................................................................................................................................................  87 

3.26.3.  Des propriétés ...................................................................................................................................................  87 

3.26.4.  Type dynamique et liaison tardive .....................................................................................................................  88 

3.27.  L’héritage ...................................................................................................................................................  90 

4.  Complexité ...................................................................................................................................... 95 

4.1.  Complexité temporelle d’un algorithme ....................................................................................................  95 

4.2.  Complexité spatiale d’un algorithme .........................................................................................................  97 

4.3.  Comportement asymptotique ...................................................................................................................  97 

4.3.1.  Définitions et notations .....................................................................................................................................  97 

4.3.2.  Règles de simplification .....................................................................................................................................  99 

5.  Quelques stratégies ...................................................................................................................... 103 

5.1.  Algorithmes itératifs et invariants de boucle ...........................................................................................  103 

5.1.1.  Le principe .......................................................................................................................................................  103 

5.1.2.  Quelques types classiques d’invariants ...........................................................................................................  105 

5.2. 

Algorithmes récursifs

 et

 l’approche

 « Diviser

 pour

 régner

 » ...................................................................

 110

 

5.2.1.  La récursivité ....................................................................................................................................................  110 

5.2.2.  « Diviser pour régner » ....................................................................................................................................  117 

6.  Conventions .................................................................................................................................. 121 

6.1.  Conventions de nommage .......................................................................................................................  121 

6.1.1.  Variables, paramètres, fonctions et procédures ..............................................................................................  121 

6.1.2.  Classes (Modules/Modèles) .............................................................................................................................  121 

6.1.3.  Constantes .......................................................................................................................................................  121 

6.2.  Conventions d’indentation ......................................................................................................................  122 

7.  Les fichiers dans eclipse ................................................................................................................ 123 

7.1.  Importer un fichier source .......................................................................................................................  123 

7.2. 

Importer une

 archive

 zip

 contenant

 un

 projet

 ........................................................................................

 124

 

7.3.  Exporter un projet sous forme d’archive zip ...........................................................................................  125 

Page 5: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 5/199

Introduction  Programmation Zoom sur l’ordinateur  [email protected] – B227 

3

7.4.  Ajouter une bibliothèque Jar à son projet ...............................................................................................  126 

8.  Dépôt de fichiers sur campus ........................................................................................................ 127 

8.1.  La procédure ............................................................................................................................................  127 

8.2.  Erreurs à ne pas commettre ....................................................................................................................  130 

8.2.1.  Déposer via la session d’un autre ....................................................................................................................  130 

8.2.2.  Déposer un mauvais fichier ..............................................................................................................................  130 

8.2.3.  Ecraser un fichier .............................................................................................................................................  130 

9.  Principaux messages d’erreur ....................................................................................................... 131 

9.1.  Messages du compilateur ........................................................................................................................  131 

9.2.  Messages de la machine virtuelle  java .....................................................................................................  134 

10.  Mémento ....................................................................................................................................... 135 

10.1.  Types de base ...........................................................................................................................................  135 

10.2.  Principaux opérateurs ..............................................................................................................................  135 

10.3.  Mots réservés ..........................................................................................................................................  138 

11.  S’exercer ? ..................................................................................................................................... 139 

11.1. 

Les étapes

 ................................................................................................................................................

 139

 

11.1.1.  Comprendre parfaitement le cahier des charges .............................................................................................  139 

11.1.2.  Comment JE parviens à réaliser une telle tâche ? ............................................................................................  139 

11.1.3.  Quand la tâche est‐elle terminée ? ..................................................................................................................  139 

11.1.4.  S’exprimer en Java ...........................................................................................................................................  139 

11.1.5.  Vérifier sa solution ...........................................................................................................................................  139 

11.1.6.  Refaire l’exercice ..............................................................................................................................................  139 

11.2.  Sur un exemple ........................................................................................................................................  140 

12.  Glossaire ........................................................................................................................................ 141 

13.  Exercices de cours ......................................................................................................................... 151 

13.1.  Enoncés ....................................................................................................................................................  151 

13.2. 

Corrigés ....................................................................................................................................................  175 

Page 6: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 6/199

 

Introduction  Programmation Zoom sur l’ordinateur  [email protected] – B227 

Page 7: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 7/199

Introduction  Programmation Zoom sur l’ordinateur  [email protected] – B227 

5

2. Introduction

2.1.  Zoom sur l’ordinateur

Si vous avez à expliquer à votre grand-mère le fonctionnement d’un ordinateur vous verrez très viteque vous ne pourrez pas faire l’économie de quelques détails. Vous commencerez surement par décrireles éléments visibles « ça c’est le clavier, là t’as le lecteur de DVD, ça c’est où tu peux mettre la carte deton appareil photo, … » et les opérations à suivre pour l’utiliser « tu allumes en appuyant sur ce bouton,t’attends, ensuite tu tapes ton mot de passe et tu te retrouves avec les icones des programmes à l’écran.Pour charger tes photos tu … ». Mais pour expliquer qu’il est important de sauvegarder son travail avantde quitter un logiciel vous serez surement amené(e) à faire la distinction entre mémoire vive et mémoirede masse, et à parler de l’arborescence des disques durs lorsqu’il s’agira de retrouver ses fichiers.

Pour apprendre à programmer, il n’est pas vraiment indispensable de suivre un cours d’électroniqueexpliquant comment exploiter une porte logique. Nous ne descendrons pas jusqu’à ce niveau de détails.Vous trouverez dans cette section une présentation sommaire, voire simpliste, de l’ordinateur et de son

fonctionnement. Des éléments que certains d’entres vous ne maitrisez peut-être pas encore et qui peuventaider à la compréhension du reste de ce cours.

2.1.1.  Le matériel

L’ordinateur n’est qu’une machine à exécuter des programmes. Une analogie musicale pourrait décrirel’ordinateur comme un orgue de barbarie et les programmes comme les cartes trouées permettant de jouerdiverses mélodies.

Le cœur de l’ordinateur, le  microprocesseur, est principalement constitué d’une unité de contrôle,d’une unité de calcul arithmétique et logique et de  registres. L’unité de calcul sait réaliser un nombrelimité d’opérations, et cette liste d’opérations varie d’un type d’ordinateur à un autre. Les registres,

qui sont toujours en très petit nombre, sont des cases mémoire permettant de stocker de l’informationtemporairement pendant un calcul. Une opération réalisée par l’unité de calcul peut être de mémoriser uneinformation dans un registre, d’additionner une valeur à un registre et de placer le résultat dans un secondregistre ou encore tester si une valeur vaut 0. Ces opérations peuvent prendre une ou plusieurs opérandes.Tout, aussi bien les données que les opérations, sont codées par des bits (un  bit, pour Binary digIT , étantl’unité minimale d’information et vaut soit 0, soit 1). Si un microprocesseur a des instructions sur XX

 bits, il utilisera quelques-uns de ces bits pour le code de l’opération (par exemple 0110 pour l’addition) etle reste pour les opérandes.

Les  programmes  (qui ne sont que des suites d’instructions) et les données sont mémorisés dans la mémoire vive. Cette dernière peut être vue comme un immense vecteur de bits regroupés en mots. Un mot est l’unité de mémoire adressable. Les ordinateurs peuvent avoir des mots de 8, 16, 24, 32, 48 ouencore 64 bits. Si par exemple les adresses sont codées par 32 bits (variable d’un ordinateur à l’autre), il ya 232 = 4.294.967.296 adresses différentes et si chaque adresse désigne un mot de 8 bits (un octet) c’estune mémoire de 4 Go qui est adressable.

L’unité de contrôle est le chef d’orchestre. Elle charge depuis la mémoire l’opération à réaliser,demande à l’unité de calcul de réaliser l’opération, et passe à l’opération suivante. Contrairement àl’orgue de barbarie, le déroulement des instructions n’est pas linéaire. L’opération suivante est souventl’opération qui vient juste après en mémoire, mais certaines opérations permettent de « sauter » à uneautre instruction du programme, ceci afin de répéter une série d’opérations (Un peu comme lesmentions « refrain » ou « bis » d’une partition)  ou de conditionner une action au résultat d’un calcul (donc, pour ne réaliser une tâche que sous certaines conditions).

Des bus, des nappes de fils électriques au travers desquels transite l’information, relient ces différents

éléments et une  horloge cadence le déroulement des programmes. Enfin, des  périphériques permettentles échanges, en entrée (clavier, souris, écran tactile, micro, …) ou en sortie (écran, imprimante, graveur,haut-parleurs, …).

Page 8: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 8/199

 

Introduction  Programmation Les langages de programmation  [email protected] – B227 

 Notez que les deux opérations disponibles sur la mémoire vive sont la lecture (on consulte la valeurmémorisée dans une case) et l’écriture (on mémorise une valeur dans une case). On ne peut pas« vider » une case mémoire, on peut tout au plus écraser la valeur contenue dans une case par unenouvelle valeur. La mémoire vive, qu’on retrouve sous forme de barrettes dans les ordinateurs est rapide,mais chère et le maintien de l’information en mémoire requiert de l’électricité. Si on coupe

l’alimentation, le contenu de la mémoire vive est perdu . Pour pallier à cela, les ordinateurs comportentde la mémoire de masse. De la mémoire moins rapide, mais aussi moins chère, plus volumineuse et quine perd pas l’information si on coupe l’alimentation. Il s’agit des disques durs, DVD-Rom et autres clefsUSB. Les programmes et les données sont donc mémorisés de manière « pérenne » dans la mémoire demasse et sont copiés dans la mémoire vive lorsque le microprocesseur doit travailler sur eux.

2.1.2.  Le logiciel

Parmi les logiciels on peut distinguer :-  Le BIOS (Basic Input/Output System) qui est exécuté en premier au démarrage. Il vérifie le bon

fonctionnement de différents composants de l’ordinateur, permet à l’utilisateur de configurercertaines options de sa configuration, et propose au système d’exploitation des fonctionnalités de

 bas niveau pour l’exploitation des périphériques.-  Le système d’exploitation (S.E. ou OS pour Operating System) qui gère les ressources matérielleset logicielles. Il gère entre autres les  processus  (les programmes en cours d’exécution), lamémoire, l’accès aux périphériques et le système de fichiers de la mémoire de masse. Lessystèmes d’exploitation proposent une interface textuelle via un interpréteur de commandes  etune interface graphique via un gestionnaire de fenêtres.

-  Les applications que sont les autres programmes lancés par l’utilisateur comme un traitement detexte ou un logiciel de retouche d’images.

2.2.  Les langages de programmation

La plupart des programmes que vous utilisez sont directement exécutables. Ils sont fournis sous laforme d’un ou plusieurs fichiers contenant une série (potentiellement énorme) d’instructionscompréhensibles par l’ordinateur. S’ils sont compréhensibles par la machine, ils ne le sont que trèsdifficilement par un humain puisque tout est codé par des bits.

Plutôt que de taper des 0 et des 1, les programmeurs s’expriment dans un langage de programmation.Ce qu’ils produisent, le programme écrit dans un certain langage de programmation, est appelé  code

 source. Une phase de traduction, appelée  compilation, est ensuite nécessaire pour obtenir du codeexécutable.

Certains langages, comme l’assembleur, sont dits de bas niveau. Les mots du langage désignent desinstructions du système. Ces langages sont donc dépendants du système pour lequel ils ont été conçus. Sion veut développer un programme pour un autre système, il faut changer de langage de programmation.

Fig. 2.2.1 – Avec des langages de bas niveau les codes sources sont spécifiques à un système.

Les langages de haut niveau (la liste est longue mais on peut citer entre autres Basic, Caml, Cobol,Fortran, Haskell, Java, Lisp, Pascal, Php, Prolog, Python, Ruby, Smalltalk) font abstraction des

Code Source pour 

Linux x86 

Code Source pour 

Linux x64 

Code Source pour 

Solaris x64 

Code Source pour 

Windows x64 

compilation

compilation

compilation

compilation

Exécutable 

Linux x86

Exécutable 

Linux x64

Exécutable 

Solaris x64

Exécutable 

Windows x64

Page 9: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 9/199

Introduction  Programmation Les phases du développement  [email protected] – B227 

7

spécificités du système. On peut les employer pour réaliser des programmes qui fonctionneront sur plusieurs types de machines. Des compilateurs (programmes de traduction) permettent de générer à partirdu code source des programmes exécutables pour les différents types d’ordinateurs. Pour certainslangages des interpréteurs  sont également fournis. Ils assurent eux aussi la traduction en langagemachine, mais à la volée. Plutôt que de produire une traduction de l’ensemble du code source, ils

traduisent au fur et à mesure de l’exécution.

Fig. 2.2.2  –  On  peut générer  les exécutables  pour  divers systèmes à  partir  d’un code source écrit dans un langage de haut niveau.

Une des clefs du succès du langage java est sa portabilité. Le code source écrit en java est d’abordcompilé dans un langage intermédiaire appelé  bytecode  (pseudo-code java). Le résultat de cette

compilation est interprétable par n’importe quelle machine virtuelle Java (JVM). Le même bytecode peutdonc être utilisé sur tous les systèmes, pour peu qu’une machine virtuelle java ait été installée surl’ordinateur 1.

Fig. 2.2.3  –  Le bytecode résultant de la compilation d’un programme java peut être interprété sur tout système d’exploitation.

2.3.  Les phases du développement

Programmer c’est rédiger une marche à suivre pour faire faire une tâche, en différé, par un exécutantaux capacités limitées qu’est l’ordinateur.

 Nous avons tous eu entre les mains des marches à suivre, qu’il s’agisse d’une recette de cuisine oud’un guide d’installation d’un appareil électronique. Cette fois, il va s’agir de concevoir une marche àsuivre, ce qui sous entends notamment savoir décomposer une tâche en un ensemble d’opérationsélémentaires mais aussi savoir exprimer notre marche à suivre dans un langage de programmation ouencore savoir trouver des erreurs (bugs) dans un code source.

 Notre exécutant est discipliné. Il fait exactement ce qu’on lui demande. Si ce qu’il fait ne correspond pas à nos attentes on ne peut donc en vouloir qu’au programmeur. Il est aussi courageux. Si on demande àun ordinateur de commencer la réalisation d’une tâche qui lui demandera plusieurs millions d’années il semettra au travail sans discuter. Qui plus est, les programmes que nous écrirons pourront être exécutés ennotre absence. Nous ne serons pas toujours à coté de l’ordinateur pour rectifier nos erreurs. Il convientdonc de vérifier la validité de nos programmes AVANT leur utilisation tout comme de savoir

estimer le temps requis afin de s’assurer que l’ordinateur sera en mesure d’effectuer la tâche en untemps raisonnable.

Faisons le point sur quelques étapes menant à l’obtention de programmes valides.

2.3.1.  La phase de spécification

 Le bon informaticien ne commence pas par apporter des solutions mais par poser les bonnes questions

La toute première question à se poser est « Quelle est la tâche ? ». Ca peut paraître idiot, et ça ne vousviendrait peut-être pas à l’esprit, mais bon nombre de personnes (y compris des élèves ingénieurs) se

1 Java est inclu dans certains systèmes d’exploitation comme MAC OS. Des Java Runtime Environment  (JRE) incluant une machine virtuelle sontdisponibles pour la plupart des autres systèmes d’exploitation.

Code Source en Java  compilation

 

Bytecode interprétable par n’importe quelle machine 

virtuelle  java 

Compilations Code Source en langage 

de haut niveau

Exécutable 

Linux x86

Exécutable 

Linux x64

Exécutable 

Exécutable 

Windows x64 

Page 10: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 10/199

 

Introduction  Programmation Les phases du développement  [email protected] – B227 

mettent à proposer des solutions avant même d’avoir clairement compris ce qui est attendu. Que dire d’un programme hors-sujet ? Notre travail est de décortiquer la tâche à accomplir jusqu’à pouvoir l’énoncercomme un ensemble ordonné de tâche que l’ordinateur sera capable d’accomplir. Cette décorticationexige entre autres qu’on connaisse précisément les entrées (les données nécessaires au traitement) et les

 sorties (ce qu’on s’attend à obtenir une fois la tâche réalisée). Cette phase de spécification qui consiste en

quelque sorte à établir le cahier des charges est indispensable mais les spécifications vous serontgénéralement fournies dans le cadre de ce cours puisqu’elles résultent de discussions avec le client(Longues discussions car on doit se mettre d’accord sur tous les détails de ce qui est désiré).

2.3.2.  La phase de modélisation et de découpage

On n’écrit pas une rédaction sans avoir bâti un plan. La phase de modélisation va dresser l’architecturede votre programme en établissant un découpage en plusieurs sous-parties. La question à se poser estalors « Quelles parties se dégagent pour mon programme ? ». Comme en programmation par objets sedécoupage s’articule généralement autour de la représentation des données traitées cela revient à se poser

la question « Quels types d’objets seront manipulés par mon programme ? » car il y aura une partie denotre programme consacrée à chacun de ces types. La tâche globale est alors décomposée en la réalisationde plus petites tâches. Nous verrons en fin de section l’intérêt du découpage.

2.3.3.  La phase d’analyse

Solving a problem gives you the solution. Knowing how you solved the problem gives you a program

La question suivante est « Comment faire ? ». Il s’agit de déterminer comment parvenir aux résultatsrecherchés à partir des entrées. Il est souvent plus délicat d’expliquer comment on fait que de faire. Ainsi,

si je donne un jeu de 32 cartes et que je vous demande de les classer, vous allez le faire facilement etrapidement. Mais ce qui est demandé ici c’est de décrire la façon d’y parvenir, d’énoncer la stratégieemployée, laquelle stratégie ne sera pas forcément la même d’un trieur de cartes à un autre puisqu’il y a

 bien évidemment plusieurs façons de parvenir au résultat.

2.3.4.  La phase de conception

On dit ensuite se demander « comment faire faire ? ». L’analyse a permis de cerner « commentfaire » et il nous faut à présent l’exprimer pour rendre l’ordinateur capable de réaliser la tâche. C’est làque notre connaissance des capacités de notre exécutant est importante puisqu’on va décortiquer lestâches à réaliser en une succession de tâches dont l’ordinateur est capable.

Le langage naturel est inadapté car ambigüe (ex. : « Le boucher sale la tranche » où l’on ne sait pas siil s’agit de sel ou de crasse ou « j’ai lu la critique de Romuald » où l’on ne sait pas si j’ai critiqué ou si

 j’ai été critiqué). On utilise généralement un langage algorithmique, une sorte d’abstraction de quelqueslangages de programmation mais dans le cadre de ce cours nous utiliserons directement Java. Commevous le verrez, un langage de programmation est bien plus simple à appréhender que n’importe quellelangue étrangère puisque le vocabulaire et les règles de grammaire sont assez limités.

Pour une même tâche, plusieurs stratégies (et donc plusieurs algorithmes) peuvent être proposés. Ilnous faudra alors choisir en fonction de différents critères, comme la complexité (qui reflète la rapidité del’algorithme) ou encore la clarté et la simplicité (afin de faciliter la maintenance du programme). 

Description précise de la tâche 

sur papier  SpécificationQuoi faire ?Désirs flous du client

Description précise de la tâchesur papier  Spécification

Quoi faire ?Désirs flous du client Découpage en sous-tâches 

sur papier  Parties ?Quelles

Spécification 

Quoi faire ?  Comment faire ? 

Analyse 

Quelles parties ?

Modélisation

Désirs flous du clientdans son esprit

 

Description de la tâchesur papier

en langage naturel 

Stratégiessur papier

en langage naturel

Découpagesur papier

en langage naturel

Désirs flousdu client

dans son esprit 

Description de la tâche papier  

langage naturel Spécification 

Quoi faire

 ? 

Stratégies papier  

lang. naturel

Algorithme papier  

lang. algorithmique

Comment 

faire ? 

Analyse

Comment 

faire faire

 ? 

Conception 

Quelles 

parties ? 

Modélisation

Découpage papier  

lang. naturel

Page 11: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 11/199

Introduction  Programmation Les phases du développement  [email protected] – B227 

9

Désirs flous

du clientcerveau 

Description

de la tâche papier lang. nat. cation 

Spécifi‐ Stratégies

papierlang. nat.

Algorithme

papierlang. Algo.

Code Source

fichierlang. prog. .mentation 

Analyse   Concep‐

tion

Exécutable

fichierbytecode

Compi‐

lation

Implé‐Découpage

Papierlang. nat.sation 

Modéli‐

Leprogrammeest correct ?

non

tests

 

2.3.5.  L’implémentation

Il s’agit de répondre à la question « comment dire ? », ou plutôt comment nous exprimer au mieux pour tirer parti du langage de programmation retenu. Puisque nous n’utiliserons pas de langagealgorithmique, cette phase peut paraître confondue avec la précédente mais il s’agit cette fois d’aboutir à

du code source, donc à du code énoncé dans notre langage de programmation (Java en ce qui concerne cecours) et mémorisé dans un fichier informatique.

2.3.6.  La compilation

L’étape la plus simple et la plus rapide puisqu’elle consiste à demander au compilateur de générer le bytecode correspondant à notre code source. Notons que s’il est aisé de faire traduire un code source en bytecode, il n’en va pas de même pour l’opération inverse. C’est donc le code source que le développeursauvegarde précieusement afin de ne pas perdre le fruit de son labeur, le bytecode pouvant lui être généré

à nouveau à partir du code source.

2.3.7.  Débogage

 L’erreur est essentiellement humaine

La capacité de l’Homme à commettre des erreurs est sans égal. Il y a donc fort à parier que le processus de développement le conduise à en réaliser de nombreuses, potentiellement à chaque étape. Desdésirs du client ont pu être « oubliés » lors de la spécification, et le développeur n’en prendragénéralement conscience que lors d’échanges avec le client. Les erreurs de syntaxe et de grammairecommises lors de l’implémentation seront les plus simples à corriger puisque le compilateur va les

indiquer en soulignant l’endroit concerné dans le code source. Les autres erreurs sont dites « de logique »et résultent soit d’une mauvaise traduction de l’algorithme, soit (et c’est plus grave) d’erreurs dans l’algo-rithme. Ces erreurs de logique sont bien plus difficiles à déceler, à identifier et à corriger. En effet, c’est

 bien souvent via un « comportement inattendu » du programme à l’exécution qu’on les détecte. Dès lors,le développeur doit prendre sa casquette de fin limier et tenter de localiser l’erreur dans le code source.

Bien souvent il s’agit de se mettre à la place de l’exécutant et de tracer l’exécution, c'est-à-dire suivre pas à pas le déroulement, jusqu’à trouver ce qui cloche, aidé en cela par des outils de débogage. Puis unefois l’erreur corrigée à recompiler et reprendre la phase de test jusqu’à éliminer toutes (on l’espère…) leserreurs. Mais essayer un programme ne peut qu’au mieux montrer qu’il est incorrect, jamaisprouver qu’il ne comporte pas d’erreurs !

Heureusement de bonnes habitudes de programmation peuventlimiter le temps consacré au débogage. Mieux vaut ainsi s’intéresser à la validité de l’algorithmeavant de débuter l’implémentation. Il vaut mieux également favoriser un algorithme simple  si ses

 performances sont acceptables plutôt que d’utiliser une usine à gaz qui n’apporte que peu d’avantages.Commenter (et employer des noms significatifs tout au long du code) et documenter le programme estindispensable pour aider la (re)lecture du code source. Enfin, découper la tâche en plusieurs sous-tâches est salutaire. D’une part la probabilité est plus faible de faire des erreurs en s’attaquant à des sous-tâches simples (même nombreuses) qu’en se confrontant à une énorme tâche complexe. D’autre part, on

 pourra plus facilement localiser l’erreur. Enfin, mais on sort du cadre du débogage, le découpage en sous-tâches est indispensable pour des projets importants où le travail s’effectue en équipe.

Désirs flousdu clientcerveau 

Descriptionde la tâche 

papier lang. nat. Spécification 

Quoi faire ? 

Stratégies papier

lang. nat.

 Algorithme papier

lang. Algo. 

Code Source fichier

lang. de prog

Comment dire ?

Implémentation

Comment faire ?

Comment faire faire ? 

Analyse Conception 

Découpage papier

lang. nat.

Quelles parties ?

Modélisation

Désirs flousdu clientcerveau 

Descriptionde la tâche 

papier lang. nat. cation 

Spécifi‐ Stratégiespapier

lang. nat.

Algorithmepapier

lang. Algo.

Code Sourcefichier

lang. prog. .mentation 

Analyse   Concep‐

tion

Exécutablefichier

bytecode

Compi‐

lation

Implé‐Découpage

Papierlang. nat.sation 

Modéli‐

Page 12: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 12/199

 

10 

Introduction  Programmation Conventions d’écriture  [email protected] – B227 

2.4.  Conventions d’écriture

Dans ce qui suit, tout texte en police courrier new, comme public class Test { },correspond à du code source java. La police arial  est elle utilisée pour les noms de fichiers (commeTest.java) ainsi que les textes apparaissant dans les interfaces (comme File | New | Java Project).

2.5.  Les outils

Pour programmer en Java il suffit d’avoir installé le Kit de Développement Java (JDK). L’écriture ducode source peut en effet se faire dans un banal éditeur de texte. Toutefois, pour rendre le développement

 plus agréable, nous utiliserons l’environnement de développement Eclipse.

Le JDK et Eclipse ont déjà du être installés sur votre ordinateur avec l’aide du SIC. Cette sectionrevient sur l’installation de ces outils au cas où vous auriez à les réinstaller.

2.5.1.  Installation du Kit de Développement Java (JDK)

Si votre ordinateur est un MAC récent vous ne devriez pas avoir à installer de JDK car ce dernier estinclus dans les dernières versions de MAC OS. Si ce n’est pas votre cas, suivez les étapes suivantes.-  Consultez la page http://www.oracle.com/technetwork/java/javase/downloads/index.html  (vous

retrouverez cette adresse en tapant « jdk download » dans Google).

-  Cliquez sur (peu importe si la version n’est pas 8u5)-  Dans la fenêtre qui s’ouvre, (1) cliquez devant « Accept Licence Agreement » puis (2) sur la

version adaptée à votre système d’exploitation. Notez que « Windows x64 » fait référence à laversion 64 bits de Windows alors que « Windows x86 » correspond à la version 32 bits2.

-  Choisissez d’enregistrer le fichier pour lancer le téléchargement.-  Une fois le téléchargement achevé, double-cliquez sur le fichier récupéré et suivez les étapes

d’installation (généralement en cliquant sur « next »).-   Notez qu’une fois l’installation terminée vous n’avez plus rien à faire concernant le JDK. En effet,

vous écrirez vos programmes sous Eclipse et n’utiliserez pas directement le JDK.

2

 Si vous êtes sous Windows mais que vous ignorez si votre version est 32-Bits ou 64-Bits appuyez sur la touche Windows et la touche Pause 

( ou allez dans le menu « Démarrer  », sélectionnez « Panneau de configuration  » puis « Système  et sécurité » et enfin« Système ») et vous verrez l’information à coté de « Type de système ». 

Page 13: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 13/199

Introduction  Programmation Les outils  [email protected] – B227 

11 

2.5.2.  Installation d’Eclipse

-  Consultez la page http://www.eclipse.org/downloads/  (vous retrouverez cette adresse en tapant« eclipse download » dans Google).

-  Téléchargez

en (1) sélectionnant votre système d’exploitation puis (2) en cliquant sur votre version d’OS dansla section « Eclipse Standard ».

-  Pour installer Eclipse il suffit de décompresser/dezipper le fichier récupéré : déplacez le fichiertéléchargé dans le dossier où vous désirez installer Eclipse (Peu importe l’endroit, il n’y a asd’obligation que ce soit dans C:\Programmes) puis faites un clic-droit et sélectionnez « extrairetout… » (ou utilisez un utilitaire comme 7-zip).

Avant de lancer Eclipse nous allons créer un raccourci puis un dossier dans lequel seront placéestoutes vos réalisations.

-  Dans le dossier décompressé, faites un clic-droit sur l’icône d’Eclipse et sélectionnez « Créerun raccourci ». Déplacez ce raccourci sur le bureau pour pouvoir accéder à Eclipse facilement.

-  Faites un clic-droit sur une partie dégagée de votre bureau et sélectionnez « nouveau » puis« dossier  ». Nommez ce dossier « workspace ».

-  Lors du lancement d’Eclipse nous allons devoir lui préciser que c’est dans ce dossier que noustravaillerons et vous devez donc connaître son emplacement. Pour cela, faites un clic-droit sur ledossier « workspace » et choisissez « propriétés ». Notez le chemin indiqué en face de« Emplacement : » (C:\Users\rdebruyn\Desktop dans l’exemple ci-dessous).

1

2

Page 14: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 14/199

 

12 

Introduction  Programmation Les outils  [email protected] – B227 

-  Lancez Eclipse en double-cliquant sur le raccourci placé sur votre bureau. Une fenêtre vous inviteà préciser le répertoire de travail. Désignez votre dossier workspace  (l’emplacement suivi de« \workspace », donc « C:\Users\rdebruyn\Desktop\workspace » dans l’exemple ci-dessous).

 Notez que vous pouvez également utiliser le bouton « Browse… » pour aller désigner le dossierworkspace dans l’arborescence de votre disque dur. Puis cliquez sur OK. Eclipse se souviendra

de votre répertoire de travail lors du prochain lancement et vous n’aurez donc plus à lui indiquermais juste à le confirmer.

-  Un onglet permettant d’accéder à des tutoriaux s’affiche lors du lancement dans un nouvel espacede travail. Fermez cet onglet qui masque l’interface d’Eclipse (Il est possible de ré-ouvrir cetonglet en sélectionnant « Welcome » dans le menu « Help ») en cliquant sur la croix (1).

-  Eclipse est opérationnel. Vous pouvez le fermer. Lorsque vous voudrez l’utiliser vous n’aurezqu’à double-cliquer sur le raccourci du bureau et confirmer votre espace de travail.

2.5.3.  Lancer Eclipse depuis un ordinateur de l’EMN

Si vous devez utiliser Eclipse sur un des ordinateurs disponibles en salle de TP il vous faut démarrerl’ordinateur sous linux (si l’ordinateur est démarré sous windows, redémarrer le). Une fois sous linux,ouvrez un interpréteur de commande/Shell/Terminal, tapez source /home/linux.eclipse/.login  etvalidez en appuyant sur la touche [Entrée]. Cette commande est indispensable pour que linux trouveeclipse. Tapez ensuite eclipse &  pour lancer Eclipse.

Page 15: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 15/199

Introduction  Programmation Les outils  [email protected] – B227 

13 

Résumé-  Dans un ordinateur les programmes et les données sont stockés de manière « pérenne » dans la

mémoire de masse (disque dur, DVD, …).-  Le microprocesseur charge en mémoire vive (sensible aux coupures d’alimentation) les

 programmes et les données qu’il doit traiter.-  Les systèmes d’exploitation gèrent les ressources matérielles et logicielles. Ils disposent d’une

interface textuelle (l’interpréteur de commandes) et d’une interface graphique (le gestionnaire defenêtres).

-  Les opérations disponibles sur un ordinateur varient d’un système à l’autre.-  Le code source écrit dans un langage de programmation de haut niveau peut être traduit dans le

langage machine de différents systèmes via des compilateurs. On peut donc générer des programmes exécutables sur différents systèmes à partir du même code source.

-  Le bytecode obtenu par compilation d’un code source écrit en java peut être interprété parn’importe quelle machine virtuelle java, et peut donc être utilisé sur tout type de systèmes.

-  Avant de commencer à écrire le code source d’un programme il faut cerner les spécifications(quelles sont les données et qu’elle tâche doit être menée à bien), décomposer la tâche en sous-tâche si il y a lieu, se demander comment humainement on fait afin d’élaborer une stratégie, etenfin écrire un algorithme.

-  Le débogage peut prendre un temps considérable et une phase de tests peut permettre de détectercertaines erreurs mais ne prouve en rien l’absence de bugs. Mieux vaut donc s’assurer de lavalidité de nos stratégies et algorithmes avant d’écrire le code source. Mieux vaut égalementadopter de bonnes pratiques tel le découpage en sous-tâches, l’emploi de noms significatifs et decommentaires ou encore le choix d’algorithmes simples si ils ont des performances acceptables.

Page 16: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 16/199

 

14 

Introduction  Programmation 

Les 

outils  [email protected] – B227 

Page 17: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 17/199

Les  concepts de programmation  Programmation Un programme minimaliste  [email protected] – B227 

15 

3. Les concepts de programmation

 Nous allons nous exprimer dans un langage de programmation. Cet apprentissage va bien sûrs’effectuer de manière graduelle. Il est tout à fait normal que dans un premier temps vous parveniez à

comprendre les programmes que nous allons regarder sans pour autant parvenir à en écrire de similaires.On ne commence pas l’apprentissage de l’anglais par une rédaction de 30 pages. On commence parregarder des textes en essayant de les comprendre. Vous aurez remarqué également qu’on ne suit pasl’ordre lexicographique dans l’apprentissage du vocabulaire d’une nouvelle langue. On n’apprend pas non

 plus tous les temps de la conjugaison avant de voir les règles d’accord en nombre et en genre. C’est ce quiexplique l’organisation de notre apprentissage. Nous allons commencer avec un vocabulaire trèspauvre et très peu de règles de grammaire. Nos programmes seront dès lors très simples, comme les

 premières phrases « sujet – verbe – complément » que vous avez formulées dans vos premiers cours delangue vivante. Nous enrichirons notre vocabulaire et notre grammaire pour répondre à des besoinsexpressifs. L’organisation de ce support peut donc sembler bien moins organisée que la juxtapositiond’un dictionnaire et d’un manuel de grammaire. Mais cette organisation est voulue puisqu’il ne s’agit pasd’un manuel de référence, mais bien d’un support de cours.

Les objectifs fixés sous entendent l’acquisition d’un peu de savoir (nous ne verrons que les conceptsles plus généraux) mais de beaucoup de savoir faire. Il ne s’agit pas d’apprendre des récitations, maisd’apprendre à rédiger, ce qui ne s’acquiert qu’avec énormément de pratique. Il vous faudra travailler(Désolé…) sur de nombreux programmes avant de parvenir à exprimer la résolution de tâches sans tropde difficultés.

3.1.  Un programme minimaliste

Un programme peut-être vu comme un ensemble de  classes  (nous verrons ce terme dans la sectionsuivante) regroupant des  méthodes (bouts de programme réalisant une tâche bien précise) qui s’appellentles unes les autres dans un ordre cohérent pour réaliser un traitement sur des données en mémoire. Bref,quand on va exécuter un programme on va exécuter un bout de code, qui va potentiellement faire appel àun autre bout de code, qui à son tour pourra appeler d’autres bouts de codes, et cet enchainement doitconduire à la réalisation de la tâche. Mais par quel bout commencer ?

Au moins une des classes d’un programme java doit comporter une méthode principale qui sera la première méthode exécutée lors du lancement du programme. Java repère cette méthode par son entêtequi doit être exactement : public static void main(String[] args). Ne vous effrayez pas,nous verrons ce que veut dire entête, public, static, void , … tout ce qu’il y a retenir pour l’instantc’est qu’un programme comportera au moins une classe et qu’au moins une de ses classes comportera une

méthode main qui sera le point de départ lors de l’exécution.Ecrivons un programme minimaliste sous Eclipse. Une icône de souris ( ) symbolise une action à

réaliser. La première chose à faire est de créer un nouveau projet java qui contiendra l’ensemble desfichiers du programme, dans notre cas, une unique classe.

Lancez Eclipse (double-cliquez sur son raccourci puis validez votre espace de travail).

Dans le menu File sélectionnez New puis Java Project ( File | New | Java Project ).

Page 18: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 18/199

 

16 

Les  concepts de programmation  Programmation Un programme minimaliste  [email protected] – B227 

Dans la fenêtre qui s’ouvre, (1) indiquez un nom de projet (ici Coucou) puis (2) cliquez surFinish.

Dans le menu File sélectionnez New puis Java Project ( File | New | Java Project ).

Votre nouveau projet apparaît dans l’onglet Package Explorer  à gauche. Faites un clic-droit survotre projet Coucou et sélectionnez New puis Class.

(1) Donnez un nom à votre classe (ici Principale) et (2) cochez de sorte à ce qu’Eclipse inclut uneméthode main dans cette classe.

1

2

1

2

Page 19: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 19/199

Les  concepts de programmation  Programmation Un programme minimaliste  [email protected] – B227 

17 

On observe dans le Package Explorer  (à gauche (1)) que votre projet Coucou comporte parmises sources (dossier src) un fichier Principal.java. Ce fichier est ouvert dans l’éditeur (au centre(2)). Il contient la définition d’une classe nommée Principale  qui contient une méthodemain. Nous avons notre programme minimaliste ! Mais… un programme qui ne fait strictementrien puisque la méthode main ne contient aucune instruction. Pour y remédier, écrivezSystem.out.println("coucou !");  (à la lettre ! Attention, System  commence parune majuscule) juste en dessous de // TODO Auto-generated method stub.

Enregistrez Principal.java (Save dans le menu File, ou via le raccourci clavier [Ctrl]+[S]).

Exécutez le programme : faites un clic-droit sur Principal.java  dans Package Explorer   etsélectionnez Run As puis Java Application.

L’exécution provoque l’affichage du message « coucou !  » dans la console  (en bas (1)). Si deserreurs syntaxiques avaient été commises dans le code, l’onglet Problems (en bas (1)) comporterait desmessages d’erreurs.

Si vous avez lu attentivement le chapitre précédent, vous devez être surpris car nous avons pu exécuterle programme alors que nous n’avons jamais demandé sa compilation. Eclipse l’a fait automatiquement

 pour nous et le bytecode a bel et bien été généré. Pour vous en convaincre :

Dans le menu Window sélectionnez Show View puis Navigator .

1  2

1

Page 20: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 20/199

 

18 

Les  concepts de programmation  Programmation Commentaires  [email protected] – B227 

Dans la partie gauche un onglet Navigator   est apparu et propose une vue différente du projet.

Package Explorer   se focalise comme son nom l’indique sur les  packages  qui sont une façon deregrouper les classes entre elles. Certains fichiers et dossiers ne sont pas visibles avec cette vue,notamment le dossier bin qui contient le fruit de la compilation (le bytecode correspondant à notre codesource). La vue Navigator  correspond à l’organisation en fichiers et dossiers de notre espace de travail :si d’aventure vous ouvrez votre dossier workspace sur le bureau vous retrouverez la même vue à savoirun dossier Coucou contenant des sous-dossiers .setting, bin et src, ainsi qu’un fichier .classpath et unfichier .project.

3.2.  Commentaires

Les commentaires sont des indications ignorées par l’ordinateur. On en place dans le code pourfaciliter sa compréhension. On distingue :-  Des commentaires pour la javadoc. Comme nous le verrons plus tard, un outil permet de générer

automatiquement une documentation de notre code, pour peu qu’on précise les commentairesadéquats dans le code. Les commentaires javadoc commencent par /**   et se terminent par */ . Ils

 peuvent s’étendre sur plusieurs lignes et comporter des balises (telle que @param  dans l’exempleci-dessus). Nous reviendrons plus tard sur ce type de commentaires.

-  Des commentaires qui ne figureront pas dans la javadoc. Ils peuvent être sur une seule ligne. Ilscommencent alors par la séquence de caractères // et tout ce qui se trouve à droite de //  sur laligne est un commentaire. C’est le cas dans l’exemple ci-dessus de la ligne // TODO : Auto-….Ils peuvent également s’étendre sur plusieurs lignes et ils sont alors délimités par /*  et */ .

3.3.  Des données et des méthodes

Revenons sur notre vision d’un programme pour introduire les premiers concepts de programmation par objet. Un programme est un ensemble de classes contenant des  méthodes (dont une méthode main qui est le point de départ lors de l’exécution) s’appelant les unes les autres dans un ordre cohérent pourréaliser un traitement sur des données en mémoire. Cette vision d’un programme souligne :

-  On utilise une approche descendante visant à décomposer la tâche à réaliser par le programmeen plusieurs sous-tâches plus simples jusqu’à n’avoir que des tâches facilement programmables.Des méthodes sont écrites pour réaliser chacune des sous-tâches et la réalisation de la tâcheglobale s’effectue via un enchaînement adéquat d’appels à ces méthodes.

-  Les données doivent être représentées en mémoire. Le programme doit donc non seulementdécrire la suite d’opérations à réaliser pour mener à bien la tâche, mais aussi préciser commentreprésenter les données en mémoire.

Page 21: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 21/199

Les  concepts de programmation  Programmation Des données et des méthodes  [email protected] – B227 

19 

Dans la majorité des langages de programmation les données sont typées. Le  type précise d’une partcomment représenter l’information en machine (nous reviendrons sur ce point) et quelles opérations

 peuvent être accomplies sur la donnée. C’est d’une grande aide pour le développeur car l’ordinateurvérifie le respect des types (comme dans le primaire où on apprend qu’on ne peut pas additionner des

 pommes avec des poires) ce qui permet d’identifier certaines erreurs.

En Programmation Par objet   (P.P.O. en français, O.O.P. pour object oriented programming enanglais) les données sont au cœur de l’architecture du programme. Un programme est en effet constituéd’un ensemble de  classes, chaque classe décrivant un type de données en (1) précisant commentreprésenter la donnée en mémoire, et (2) en fournissant le code des différentes méthodes utiles à lamanipulation de ces données.

Une classe est la description d’un type d’objet. Un « moule » à objet. Chaque exemplaire créé (on parle d’instance) à partir d’une classe C  est un objet de type C. Une classe Voiture  par exemplemodélisera ce qu’est une voiture, et ce qu’il est possible de faire sur une voiture. On pourra ensuite créertout un tas d’objets de ce type, qui auront tous des caractéristiques communes (une couleur, un carburant,une puissance moteur, …) mais des valeurs potentiellement différentes pour ces caractéristiques (lesexemplaires n’auront pas forcément tous la même couleur, le même type de carburant, …).

Un programme étant composé d’un ensemble de classes, il n’est pas étonnant qu’une des premièresquestions à se poser après avoir bien cerné la tâche à accomplir est « Quels types d’entités serontmanipulés par mon programme » et pour chacun de ces types « Quelles opérations seront nécessaires pourmanipuler ces entités ». C’est la phase de modélisation, laquelle permet de déterminer les classes quicomposeront le programme.

Par exemple, si on veut concevoir un jeu de dames, on peut voir qu’il y aura un plateau de jeu et des pièces qui peuvent être soit des pions, soit des dames. Ces pièces ont une couleur (blanche ou noire) etune position (une case du plateau si elles n’ont pas été prises par l’adversaire). On doit pouvoir connaîtrela position d’une pièce ainsi que sa couleur. On doit également pouvoir déplacer une pièce en respectantles règles ou encore prendre une pièce d’un adversaire. Le jeu comporte également des joueurs qui portentun nom et ont un ensemble de pièces. Ils peuvent également avoir des statistiques comme le nombre devictoires et de défaites. On peut également songer à inclure un chronomètre…

Voyons nos premiers concepts sur un exemple plus simple qui ne manipule que des points d’un planmuni d’un repère cartésien orthonormé. Nous réaliserons le programme correspondant sous Eclipse au furet à mesure. La première chose à faire est de créer un nouveau projet java.

Lancez Eclipse (double-cliquez sur son raccourci puis validez votre espace de travail).Dans le menu File sélectionnez New puis Java Project ( File | New | Java Project ).

Dans la fenêtre qui s’ouvre, (1) indiquez un nom de projet (ici PointsDuPlan) puis (2) cliquezsur Finish.

1

2

Page 22: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 22/199

 

20 

Les  concepts de programmation  Programmation Classe  [email protected] – B227 

3.4.  Classe

3.4.1.  Nom d’une classe

Une classe doit porter un nom exprimant le type de données qu’elle modélise.  Nous suivrons laconvention adoptée dans la communauté Java selon laquelle les noms des classes sont une suitecontinue (pas d’espaces !) de caractères non accentués ou de chiffres commençant par unemajuscule. Si le nom résulte de la juxtaposition de plusieurs mots, la convention précise que chaque motcommence par une majuscule.

Exemples-  Point, Pion, Joueur, Voiture, PaquetDeCartes  ou encore AvionAReaction  sont

des noms de classes valides et qui explicitent le type de données représentées.-  classe2ceFichu%$^@deBor..l2M…eQuim’énerve n’est pas valide (des caractères sont

non autorisés et de plus le nom commence par une minuscule) et si l’agacement est exprimé letype de données n’est pas explicité.

-  MaClasseVersion7, Donnee3b35c  et C  sont des noms valides mais pas suffisammentexplicites.

Enfin, le langage Java comporte un certain nombre de mots qui ont déjà une signification bien précise.Pour qu’il n’y ait pas de confusion, nous ne pourrons pas utiliser un mot du langage pour nommer uneclasse.

3.4.2.  Déclaration d’une classe

Une classe java doit figurer dans un fichier portant exactement le même nom (Attention, java fait ladistinction entre majuscules et minuscules) mais avec l’extension « .java  ». Par exemple, la classePoint  sera écrite dans un fichier de nom Point.java. Les mots réservés public class  servent à

déclarer la classe et les accolades { et } délimitent obligatoirement le contenu de la classe.Exemple : fichier Point.java

 public class Point { // ici figurera le contenu de la classe

}

Dans la partie gauche, faites un clic-droit sur votre projet PointsDuPlan  et sélectionnez New  puis Class.

Dans la fenêtre qui apparaît, (1) indiquez Point pour nom de classe puis (2) cliquez sur Finish.

1

2

Page 23: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 23/199

Les  concepts de programmation  Programmation Classe  [email protected] – B227

 

21 

3.4.3.  Variables d’instance

Comme nous l’avons évoqué, une classe va modéliser un type de données en précisant son état (comment représenter la donnée en mémoire) et son  comportement  (les méthodes permettant lamanipulation de la donnée). L’état d’un objet est représenté par des variables d’instance (ou attributs).

Une variable est une case mémoire. Ce nom tient au fait que le contenu de la case peut évoluer dans letemps. Seules deux opérations peuvent être réalisées sur une case mémoire : la consultation et lamodification. On peut donc lire le contenu de la case ou écrire dans la case. Une case n’est jamais vide, eton ne peut donc pas la vider, on peut juste écrire une valeur dedans, remplaçant ainsi l’ancienne valeur.

Une variable d’instance est une variable servant à mémoriser une caractéristique d’un objet. Elles sont précisées dans la classe et chaque instance de la classe aura son propre exemplaire, avec une valeur potentiellement différente d’un objet à l’autre.

Les variables sont typées. Elles peuvent être d’un  type primitif  (un des types atomiques prédéfinis enJava) ou être des références (des cases contenant l’adresse en mémoire d’une donnée de type composite,comme un objet par exemple).

Les types primitifs étant prédéfinis, Java sait comment les représenter en mémoire par une sériede 0 et de 1 (puisque d’un point de vue physique tout est représenté uniquement avec des bits). Plus on ade bits, plus le spectre de valeurs représentables est grand. Avec i bits, il est possible de représenter 2i entiers différents. Chaque langage de programmation comporte des entiers et des flottants, mais d’unlangage à un autre le nombre de bits utilisés pour les représenter peut varier, et avec lui la plage devaleurs représentables. En java par exemple, les int sont codés sur 32 bits et peuvent prendre des valeursde -231 à 231-1 (-2147483648 à 2147483647). Si les valeurs que peuvent prendre une donnée entière sontmoins importantes on peut utiliser le type short (8 bits, -128 à 127) ou byte (16 bits, -32768 à 32767).Si au contraire elles peuvent dépasser les limites du type int, on peut utiliser le type long (sur 64 bits).Le tableau ci-dessous résume les caractéristiques des types primitifs. Notez que contrairement aux nomsdes classes, le nom des types primitif commence par une minuscule. On peut ainsi visuellementdistinguer les types primitifs des autres.

Type Description Exemples de valeurs

 byte Entiers signés sur 8 bitsde -27 à (27-1) (de –128 à 127)

-12,  0,  120,  0x10  (16  en 

héxadécimal), …

short Entiers signés sur 16 bitsde –215 à 215-1 (de –32768 à 32767)

-16000, 2005, 0x22, … 

int Entiers signés sur 32 bitsde –231 à 231-1 (de –2147483648 à 2147483647)

-12, 2000000000, … 

long Entiers signés sur 64 bitsde –263 à 263-1 (de –9223372036854775808 à 9223372036854775807)

-200000000000000000L, 421, … 

float Nombres à virgule flottante sur 32 bitsde 2-149 à (2-2-23).2127 

-1.0f,  3.40282347E+28, 2.5f, 6.55957f, … 

double Nombres à virgule flottante sur 64 bitsde 2-1074 à (2-2-52).21023 

-1.0d,  2.5,  6.55957, 2.8E+1000, … 

char Caractères Unicode sur 16 bits '\u00e9' (é), 'é', 'a', … 

 boolean Booléens true, false 

Les 

types 

 primitifs 

en 

 java. 

Si vous tapez une valeur entière dans le code d’un programme (une valeur littérale entière) elle seraconsidérée comme de type int à moins que vous ne la suffixiez d’un L (comme 1234L) auquel cas ellesera de type long. De même, un nombre à virgule (c’est en fait un point qui est utilisé pour séparateur)sera considéré de type double  sauf si vous le suffixez d’un f  pour qu’il soit considéré comme unfloat  (comme 2.4L). Enfin, une valeur littérale de type char  est constituée d’un seul caractèreentouré d’apostrophes (comme ‘a‘, ‘5‘,‘–‘,…). Les exceptions sont ‘\n‘, ‘\t‘  et ‘\\‘ qui

désignent respectivement le passage à la ligne, le passage à la tabulation suivante et le caractère \. Il estégalement possible de préciser un caractère via son code (ex. : ‘\u0066‘ pour le caractère unicode 66).

Page 24: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 24/199

 

22 

Les  concepts de programmation  Programmation Classe  [email protected] – B227 

Reportez vous au mémento de ce support de cours pour connaître les opérateurs java définis sur cestypes primitifs. Par exemple, l’opérateur *  correspond à la multiplication et (2.5 * 24.2)  est undouble valant le résultat du produit de 2.5 par 24.2.

Dans le cadre de ce cours nous utiliserons principalement le type int pour les entiers, double pour

les nombres à virgule, char pour les caractères et boolean pour les booléens. Vous pouvez ignorerles autres ( byte, short, long et float ) dans un premier temps.

Les variables ne sont pas créées mais réservées. Les cases mémoire sont du matériel, elles existentdéjà, et sont en nombre limité. L’ordinateur tient à jour une liste associant à chaque nom de variable uneadresse mémoire désignant l’emplacement où est stockée l’information. Cette gestion est transparente etnous n’avons qu’à retenir que ces emplacements mémoire sont désignés par leur nom (et c’est nous quiles baptisons de sorte que le nom explicite le contenu de la case mémoire).

Revenons à notre classe Point.- Par quelles données pouvons-nous représenter un point en mémoire ? Quelles données caractérisent

un point d’un plan cartésien ? … Ses coordonnées bien sûr !- De quel type sont ces données ? … Il s’agit de nombres à virgule !

En répondant à ces deux questions nous aboutissons à la définition de l’état d’un Point: il faut deuxvariables d’instance, de type double, et il parait judicieux de les baptiser abscisse et ordonnee.

On déclare un variable d’instance en ajoutant dans le corps de la classe une ligne private <type_variable> <nom_variable>; (où <type_variable> désigne le type de la

variable et <nom_variable>  son nom). Les noms de variables suivent la même convention que lesnoms de classe mais commencent par une minuscule.

Le mot réservé private permet de préciser que l’accès à ces données est privé : seules les méthodesde la classe Point  pourront directement y accéder, les autres parties du programme ne pourront lesmanipuler qu’au travers des méthodes de la classe Point. L’accès aux variables d’instance sera

toujours privé et il faut donc systématiquement préciser private  lors de la déclaration d’unevariable d’instance. Nous reviendrons plus tard sur ce point pour expliquer pourquoi il est important destipuler un accès privé. Déclarons pour l’heure les variables d’instance de notre classe Point.

Dans le corps de la class Point, déclarez : private double abscisse ; private double ordonnee ;

 Notez que :1-  Eclipse utilise la coloration syntaxique. Les mots du langage tels que public, class, private et double apparaissent en gras et violet, alors que les identificateurs introduits par

l’utilisateur tels les noms de variable n’ont pas la même couleur et ne sont pas en gras.

2-  Eclipse peut indiquer des erreurs (forcément bloquante, on ne pourra pas exécuter le programme tant qu’on n’aura pas corrigé) ou des mises en gardes (warnings, non bloquantes

12 

3

Page 25: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 25/199

Les  concepts de programmation  Programmation Classe  [email protected] – B227

 

23 

mais à consulter car elles peuvent notamment nous pointer une erreur de logique) dans lamarge. Il suffit de placer la souris sur l’icône dans la marge pour voir ce qu’Eclipse a détecté.Ici il s’agit de simples avertissements précisant qu’il est surprenant de déclarer des variablesd’instance sans qu’elles soient utilisées (Normal, nous n’avons pas encore écrit de méthodes).

3-  Attention : les erreurs détectées par Eclipse peuvent correspondre à une ancienne version de

votre code. Il faut enregistrer votre code pour être sûr que les erreurs indiquéescorrespondent bien à la version actuelle du code. Une étoile (3) à coté du nom de fichiermontre ici que des changements ont eu lieu dans le fichier depuis la dernière sauvegarde.Enregistrez le fichier en sélectionnant Save dans le menu File, en cliquant sur l’icône ouencore en utilisant le raccourci clavier [Ctrl]+[S].

4-  On retrouve l’ensemble des messages d’erreur et de mise en garde en allant dans l’ongletProblems. Double-cliquer sur un message de l’onglet Problems  vous amène à l’endroitcorrespondant dans le code.

5-  Les points-virgules sont indispensables. Ils marquent la fin d’une instruction (ici unedéclaration) et Eclipse vous signalera une erreur (et plus une simple mise en garde) si voussupprimez par exemple le point-virgule après la déclaration d’abscisse.

Il est possible de déclarer plusieurs variables d’instance de même type sur une seule ligne en lesséparant par une virgule. Ainsi, les déclarations faites dans la classe Point  sont équivalentes à private double abscisse, ordonnee ; 

Il est toutefois recommandé de veiller à la lisibilité en n’abusant pas de cette possibilité et en rajoutantéventuellement des commentaires.

La section suivante complètera cette présentation des variables d’instance en abordant les références.Ce début d’introduction aux classes s’est focalisé sur l’état. La section sur les méthode complétera cetteintroduction en abordant le comportement.

Résumé

-  Une classe sert à définir un type de données. Chaque instance créée à partir d’une classe C est un objet  de type C. Toute classe comprend un état  (les variables d’instance servant à représenterl’objet en mémoire) et un  comportement  (des méthodes pouvant être appliquées à l’objet de cetype).

-  Un programme est constitué d’un ensemble de classes dont au moins une possède une méthoded’entête public static void  main(String[] args). Cette méthode sera la premièreexécutée lors du lancement du programme.

-  Les noms de classes commencent par une majuscule et ne comprennent que des caractères nonaccentués et des chiffres.

-  Une variable est une case mémoire désignée par un nom. Les noms de variables suivent la mêmeconvention que les noms de classes MAIS commencent par une minuscule.

-  On déclare une variable d’instance au sein du corps d’une classe en précisant private suivi dutype de la variable et de son nom (et d’un point-virgule pour marquer la fin de la déclaration).

-  Les variables d’instance peuvent être d’un  type primitif   (un des types atomiques prédéfinis enJava) ou être des  références  (des cases contenant l’adresse en mémoire d’une donnée de typecomposite, comme un objet par exemple).

-  Parmi les types primitifs on utilisera principalement int  pour les entiers, double  pour lesnombres à virgule flottante, char pour les caractères et boolean pour les Booléens.

-  Il faut toujours enregistrer son code  avant de pouvoir se fiers aux messages d’erreurs et auxavertissements précisés par Eclipse.

Exercice PR001 p. 151  Corrigé p. 175 

Exercice PR002

 p.

 152

 Corrigé

 p.

 176

 

Page 26: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 26/199

 

24 

Les  concepts de programmation  Programmation Premier objet  [email protected] – B227 

3.5.  Premier objet

Après la partie état/représentation mémoire de la classe, il nous reste à voir la partie comportement, etdonc les méthodes. Mais avant cela nous allons créer nos premiers objets.

Comme nous l’avons vu, tout programme doit comporter au moins une classe possédant une méthodemain. Rajoutons donc une méthode main dans la classe Point.

Si vous n’utilisez pas un MAC, dans le corps de la class Point, en dessous de la déclaration desvariables d’instance, tapez main  puis [Ctrl]+[espace]  (maintenez la touche [Ctrl]  enfoncée puisappuyez sur la barre d’espace). Si vous êtes sur MAC, le raccourci [Ctrl]+[espace]  est par défautassocié à spotlight et il faut alors assigner un autre raccourci : allez dans le menu Window /Preferences / General / Keys puis cherchez la ligne « Content Assist » et dans Binding remplacezle Ctrl+Space par un autre raccourci, Alt+space par exemple).

Appuyez sur la touche [Entrée] pour confirmer à Eclipse le souhait d’écrire une méthode main.Taper main  [Ctrl]+[Espace] [Entrée]  est un moyen rapide d’écrire l’entête d’une méthode main mais vous pouvez bien sûr taper directement public static void  main(String[] args).

Commençons notre méthode main par l’affichage du message "Creation d’un Point".Pour cela, entre les accolades du main, tapez sysou puis appuyez sur [Ctrl]+[Espace] : sysou estremplacé par l’instruction System.out.println( ) ;  et il ne vous reste plus qu’à écrire lemessage à afficher entre les parenthèses.

Page 27: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 27/199

Les  concepts de programmation  Programmation Premier  objet  [email protected] – B227 

25 

Terminons le main en créant une instance de Point puis en affichant un dernier message. Pourcela, rajoutez les lignes ci-dessous à la méthode main :

new Point();System.out.println("Fin du programme");

Exécutez le programme : faites un clic-droit sur Point.java dans le volet Package Explorer  ou

Navigator  puis sélectionnez Run As et enfin Java Application.

L’exécution est séquentielle. Elle débute par la première instruction de la méthode main, puis ladeuxième, puis la troisième… On peut voir les deux affichages dans la console. Entre eux, un point a étécréé mais nous ne faisons rien sur ce point si bien que sa création passe inaperçue.

Toute création d’objet passe par l’opérateur new. new Point() crée une instance de Point en (1)

allouant l’espace requis pour les variables d’instance d’un Point, (2) en appelant une méthode de typeconstructeur sur l’objet alloué (nous allons très bientôt voir de quoi il s’agit) et (3) en retournant l’adressede l’objet créé (nous verrons cela dans la prochaine section). L’état de la mémoire après l’instructionnew Point() correspond au schéma ci-dessous :

Dans le schéma des tirets matérialisent l’objet pour souligner que l’instance de Point créée regroupeles variables d’instance abscisse et ordonnee.

L’instance a été créée en pure perte. D’une part parce qu’un Point  a été créé quelque part en

mémoire mais nous ne savons pas où et nous n’avons aucun moyen d’y accéder. D’autre part, commesouligné par les points d’interrogation dans le schéma ci-dessus, l’espace permettant de mémoriser lesdonnées du Point a bien été alloué mais nous n’avons mémorisé aucune valeur. Les cases ne sont pasvides, il y a une valeur à l’intérieur, mais nous ne la connaissons pas et nous n’avons pas vu commentécrire dans ces cases. Enfin, la classe Point ne contient aucune méthode d’instance et on ne peut doncdemander aucun service à un Point. Traitons ces trois problèmes dans l’ordre.

3.5.1.  Variables locales et affectation

 Nous avons besoin de mémoriser les données des objets (via les variables d’instance) mais nous avonsaussi bien souvent à mémoriser des résultats intermédiaires utiles pour la réalisation d’une tâche. Lesvariables locales  sont des cases mémoire accessible via un nom mais contrairement aux variablesd’instance (1) elles sont déclarées au sein d’une méthode, (2) elles sont allouées lorsque le fil d’exécutionatteint leur déclaration, (3) sont désallouées dès que la fin du bloc où elles ont été déclarées est atteinte et(4) on ne précise pas de visibilité (ni public, ni private).

abscisse ?

ordonnee ?

Page 28: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 28/199

 

26 

Les  concepts de programmation  Programmation Premier objet  [email protected] – B227 

Juste avant la création du point, rajoutez la déclaration : Point pt ; 

Point pt déclare une variable de type Point  et de nom pt. Comme précisé en début desection 3.4.3, puisqu’il ne s’agit pas d’un type primitif, pt est une référence. En d’autres termes, pt vamémoriser l’adresse d’un objet de type Point.

La modification de la valeur d’une variable passe par une opération appelée  affectation  dont lasyntaxe est la suivante :

<variable de type T> = <expression de type T> ;

Comme cette instruction est très utilisée mieux vaut bien saisir la tâche réalisée par l’ordinateur entraitant cette instruction. L’ordinateur commence par évaluer <expression de type T>, ildétermine donc la valeur de cette expression (ce qui peut demander éventuellement pas mal de calcul,notamment si l’expression est complexe), et ce n’est qu’une fois qu’il connaît cette valeur qu’il l’affecte àla variable <variable de type T> (il « écrit » la valeur dans la case mémoire). Bref :

-  L’ordinateur détermine la valeur de l’expression à droite du signe =. -  Cette valeur est ensuite écrite dans la variable à gauche du signe =, écrasant l’ancien contenu.

Conséquences  -  Il ne peut y avoir que l’identifiant d’une case mémoire à gauche du signe =. On ne peut

affecter que des variables. -  L’expression et la variable doivent être de même type. On ne pourra pas par exemple stocker

une valeur Booléenne dans une variable prévue pour mémoriser un entier.- 

Des expressions telles que 2=x ou (x-1)=10 sont incompréhensibles par l’ordinateur et conduirontdonc à une erreur. Attention ! Le symbole retenu en java, =, est un faux ami. Il ne s’agit pas comme enmathématique de préciser une égalité absolue et intemporelle entre deux expressions, pas plus que dedonner la définition d’une variable mathématique, et encore moins le moyen de tester l’égalité. C’est uneopération visant à modifier la valeur d’une case mémoire à un instant précis. Le contenu de la case pourra

être modifié par la suite.La valeur de l’expression new Point() est l’adresse de l’objet créé. On peut affecter cette valeur àpt afin que pt désigne/référence l’objet créé.

Remplacez la ligne new Point(); par pt = new Point(); 

Pour simplifier les explications, demandons à Eclipse de numéroter les lignes (vous n’aurez à le fairequ’une fois)

Allez dans le menu Window et sélectionnez Preferences 

Dans le volet gauche, sélectionnez General puis Editors puis Text Editors. Dans le volet droit,cochez Show line numbers.

Page 29: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 29/199

Les  concepts de programmation  Programmation Premier  objet  [email protected] – B227 

27 

L’exécution débute par l’appel de la méthode main. L’évaluation de la ligne 6 provoque l’affichagesur la console du message "Creation d’un Point". La ligne 7  déclare la variable pt. C’est à

 partir de la ligne 7 que pt existe. L’état de la mémoire juste après la ligne 7 est :

L’évaluation de la ligne 8 s’effectue en deux étapes. Tout d’abord, on évalue new Point()ce qui a pour effet de créer une instance de Point  (avec réservation des variables d’instance requises et appeld’un constructeur) puis la valeur de new Point()  (l’adresse de l’instance créée) est affectée à pt.

2

abscisse ?

ordonnee ?

?pt

3@b2pt3@b2

Page 30: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 30/199

 

28 

Les  concepts de programmation  Programmation Premier objet  [email protected] – B227 

 Notez que l’adresse 3@b2 n’est pas importante. Peu importe finalement l’adresse à laquelle l’instanceà été créée. Ce qui est important c’est de savoir que pt  contient l’adresse de l’objet créé, qu’elle leréférence. Dans nos schémas mémoire nous ne préciserons pas les adresses, et nous mettrons une flèche

 pour indiquer l’objet désigné par une référence comme ci-dessous.

L’évaluation de la ligne 9 provoque un nouvel affichage sur la console et la ligne 10 marque la fin du bloc où pt a été déclarée. pt est alors désallouée. La  portée d’une variable locale désigne la portion de programme dans laquelle la variable existe. Elle s’étend depuis la déclaration de la variable jusqu’à la findu bloc où a eu lieu la déclaration (ici de la ligne 7 à la ligne 10). A la ligne 10 le schéma devient donc :

 Nous n’avons pas à libérer l’espace occupé par les objets devenus inutiles. Java s’en charge via unmécanisme appelé  ramasse miettes  : si un objet n’est plus désigné par aucune référence il devientinaccessible et le ramasse miette « détruit » l’objet (libère l’espace mémoire qu’il occupe). C’est le cas denotre point qui va disparaitre de la mémoire. Notez qu’en java, null est une valeur pour les référencessynonyme de « ne désigne aucun espace mémoire ». Si une référence désigne un objet dont on n’a plusl’utilité il est possible d’affecter à cette référence la valeur null afin qu’elle ne désigne plus l’objet etque le ramasse miettes puisse libérer l’espace occupé par l’objet inutile.

 Notez qu’il est possible de déclarer plusieurs variables d’un même type sur une seule ligne en séparantles noms des variables par des virgules. Par exemple, int x, y, z ; déclare trois variables localesentières nommées x, y  et z. Par soucis de lisibilité il faut toutefois veiller à ne pas abuser de cette

 possibilité.

Enfin, il est possible d’initialiser (affecter pour la première fois) les variables dès leur déclaration. Parexemple, plutôt que de séparer déclaration (Point pt ;) et initialisation (pt = new Point() ;)nous aurions pu écrire Point pt = new Point() ;.

 Nous avons résolu l’un de nos trois problèmes. Nous savons à présent déclarer des références quimémoriseront l’adresse des objets créés permettant ainsi d’y accéder. Mais les variables d’instance nesont pas initialisées et la classe Point  ne disposant d’aucune méthode d’instance on ne peut riendemander aux points créées.

Résumé-  Des résultats intermédiaires peuvent être mémorisés dans des variables locales. Ces dernières sont

déclarées au sein d’un bloc de code et elles existent depuis leur déclaration jusqu’à la fin du blocdans lequel elles sont déclarées.

-  Une affectation var = exp; évalue la valeur de exp puis écrit cette valeur dans la variable var.-  On ne peut affecter que des variables. A gauche du signe = on a forcément une variable.-  On peut déclarer et initialiser (affecter pour la première fois) sur la même ligne. Par exemple,

int x = 12 ; déclare une variable locale entière x et affecte la valeur 12 à cette variable.-  Toute création d’objet passe par l’opérateur new.-  L’accès à un objet passe forcément par une référence. D’ailleurs, si un objet n’est désigné par

aucune référence, le ramasse miette libère automatiquement l’espace alloué à cet objet (l’objet estdonc « détruit » puisqu’il n’existera plus en mémoire).

abscisse

ordonnee

pt?

?

abscisse

ordonnee

?

?

 Exercice

 PR003

 p.

 153

 Corrigé

 p.

 176

 

Page 31: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 31/199

Les  concepts de programmation  Programmation Méthodes d’instance  [email protected] – B227 

29 

3.6.  Méthodes d’instance

 Nous avons défini l’état de la classe Point via des variables d’instance, mais pas son comportement.Pour cela nous allons définir des méthodes d’instance.

Il faut distinguer la déclaration d’une méthode (on la définit) de l’ appel  de méthode (on l’utilise). Ladéclaration d’une méthode comprend deux parties : une  signature (également appelé en-tête) et un corps.La signature permet de préciser les  spécifications formelles (les éventuels paramètres de la méthode, cequ’elle retourne, …) alors que le corps indique le code de la méthode, donc la suite d’instructionsréalisant la tâche. La syntaxe pour l’en-tête d’une méthode d’instance est la suivante :

<visu> <tRetour> <nomMethode>(<tArg1> <nomArg1>,…,<tArgN> <nomArgN>)

Exemples de méthodes d’instance possibles pour la classe Point

-   public double getAbscisse( )-   public double distance( Point autrePoint)-   public void  setAbscisse( double x) -   public void translater( double deltaX, double deltaY) 

On peut noter une analogie avec la définition de fonctions en mathématiques. Par exemple on pourraitdéfinir une fonction poly de R dans R qui à tout x associe 3x2-x+4. La formule peut être vue comme lecorps de la méthode, alors que la précision du nom de la fonction, du type des paramètres et du type durésultat correspond à l’en-tête. L’en-tête java précise que <nomMethode>  est une fonction de<tArg1>×<tArg2>×…×<tArgN> dans <tRetour>.

 Nos méthodes auront presque toujours public  pour visibilité (<visu>) afin que tous les autres

 parties du programme puissent y accéder. Nous verrons toutefois qu’il existe quelques cas précis danslesquels il est préférable de restreindre l’accès en précisant private au lieu de public, mais celarestera exceptionnel.

Comme en mathématique nos méthodes peuvent être des  fonctions qui donc calculent un résultat à partir des  arguments /  paramètres (nous utiliserons indifféremment les termes arguments et paramètres pour désigner les données fournies à une méthode). C’est le cas de l’exemple getAbscisse ci-dessusqui retourne un résultat de type double (l’abscisse du Point).

Mais nos méthodes peuvent également être des  procédures, et dans ce cas elles ne retournent pas derésultat. On mentionne alors void  pour type retour. Les procédures sont appelées pour l’action qu’ellesréalisent. C’est le cas de l’exemple setAbscisse qui a pour action de modifier l’abscisse d’un Point.

Pour chaque argument de la méthode on précise le type et un nom qui servira à désigner l’argument au

sein du corps de la méthode. Les éventuels arguments sont précisés après le nom, entre parenthèses etséparés par un virgule. La procédure translater citée en exemple ci-dessus prend deux paramètres detype double. Lorsqu’on fera appel à cette méthode il faudra fournir/préciser en argument deux nombresà virgule flottante. S’il n’y a aucun paramètre, les parenthèses sont quand même précisées. C’est lecas de l’exemple getAbscisse( ) ci-dessus. Notez que les arguments sont des données fournies (la

 partie du programme qui appelle la méthode donne ces informations) et il ne faut surtout pas commencerle corps par une affectation des arguments car on perd alors leurs valeurs.

Et main dans tout cela ? main est une méthode, mais une méthode de classe. Nous aborderons lesméthodes de classe bien plus tard, la seule chose à savoir pour l’instant c’est qu’on repère ces méthodes

 par le terme static  dans leur en-tête. Les méthodes qui ne sont pas static  sont des méthodesd’instance et seront par définition appelées sur une instance de la classe. Mais si j’ai créé deux points,

désignés par les références pt1 et pt2, et que j’appelle la méthode getAbscisse sur pt1, commentgetAbscisse va savoir que c’est sur pt1 et pas sur pt2 qu’elle est appelée ?

Page 32: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 32/199

 

30 

Les  concepts de programmation  Programmation Méthodes d’instance  [email protected] – B227 

Les méthodes d’instance ont toutes un argument supplémentaire, nommé this, qui désigne l’objetsur lequel la méthode est appelée (appelé l’ objet receveur car c’est lui qui reçoit le message d’invocationde la méthode). Nous n’avons pas à le préciser, il est implicite. Voyons cela sur la classe Point.

Rajoutez les méthodes getAbscisse et setAbscisse puis complétez la méthode main de

sorte que le code de la classe Point soit :1  public class Point {2   private double abscisse;3   private double ordonnee;45   public double getAbscisse( ) {6  return this.abscisse;7  }89   public void  setAbscisse( double x ) {10  this.abscisse = x;11  }12

13   public static void  main(String[] args) {14  Point pt1 = new Point();15  Point pt2 = new Point();16  pt1.setAbscisse( 2.5 );17  pt2.setAbscisse( -1.2 );18  double x1 = pt1.getAbscisse( ) ;19  double x2 = pt2.getAbscisse( ) ;20  System.out.println(x1);21  System.out.println(x2);22  }23  } 

L’appel d’une méthode sur un objet utilise la  notation pointée (appelée ainsi du fait de l’usagesyntaxique d’un point). Par exemple, pt1.setAbscisse(2.5); appelle la méthode setAbscisse sur le point désigné par pt1 avec 2.5 pour unique argument. Détaillons l’exécution de ce programme :

-  Comme nous l’avons déjà vu, la ligne 14 déclare une variable locale pt1, crée une instance dePoint  et mémorise l’adresse de cette nouvelle instance dans pt1. La ligne 15  déclare uneseconde variable locale pt2 qui référence une deuxième instance de Point. L’état de la mémoireaprès ces deux lignes est :

-  La ligne 16  appelle la méthode setAbscisse  sur l’objet désigné par pt1  avec 2.5  pour

argument. pt1 étant de type Point, Java va dérouler le code de la méthode setAbscisse dela classe Point. Les noms utilisés dans le corps de la méthode pour désigner les arguments sontappelés paramètres formels par opposition aux paramètres effectifs qui eux désignent les donnéesqui sont fournies lors d’un appel. Une variable locale est réservée pour chaque paramètre formel,ici x, mais aussi pour le paramètre implicite this. La valeur des paramètres effectifs (pt1 pourthis  et 2.5 pour x) sont recopiées dans les variables locales this  et x  avant de dérouler lecode de la méthode. L’état de la mémoire juste avant la ligne est 10 est :

abscisse

ordonnee

?

?pt1 abscisse

ordonnee

?

?pt2

abscisse

ordonnee

?

?

pt1

abscisse

ordonnee

?

?pt2

this

x 2.5

Page 33: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 33/199

Les  concepts de programmation  Programmation Méthodes d’instance  [email protected] – B227 

31 

 Notez que vu que la valeur de pt1 (l’adresse du premier point) a été recopiée dans this, this désigne lui aussi le premier point.La ligne 10  est ensuite évaluée. this  référençant le premier point, this.abscisse  est lavariable d’instance abscisse du premier point, et c’est cette variable qui est affectée avec lavaleur de x (2.5). On passe ensuite à la ligne 11 qui marque la fin de la méthode et les variableslocales (ici les paramètres formels) sont désalloués. L’état de la mémoire à l’issue de cet appelest :

-  L’appel de la ligne 16 du main étant achevé on passe à l’instruction de la ligne 17 qui lui aussifait un appel à la méthode setAbscisse mais cette fois sur pt2 et avec -1.2 pour argument.C’est la valeur de pt2 qui sera recopiée dans this et this désignera donc cette fois le second

 point. On obtient :- 

-  La ligne 18  déclare une variable locale x1  dont la portée va jusqu’à la fin de main. Pourinitialiser cette variable on évalue pt1.getAbscisse( ). pt1 étant de type Point, on appellela méthode getAbscisse()  de la classe Point  sur l’instance désignée par pt1. L’état de lamémoire juste après la ligne 5 est :

L’instruction return  sert à retourner le résultat d’une fonction. La ligne 6  retournethis.abscisse, soit 2.5. L’évaluation de pt1.getAbscisse()  donne donc 2.5  et c’estcette valeur qu’on affecte à x1.

-  La ligne 19 opère de la même façon mais cette fois l’appel à getAbscisse porte sur pt2. this désignera dès lors le second point et c’est -1.2 qui sera affecté à la variable locale x2. A l’issuede la ligne 19 on obtient :

-  Les lignes 20 et 21 affichent les valeurs de x1 et x2.-  La ligne 22 marque la fin du corps de la méthode main. On atteint la limite de la portée des

variables locales pt1, pt2, x1  et x2  qui sont dès lors désallouées. Le ramasse miette libèrel’espace occupé par les deux instances de Point que plus aucune référence ne désigne.

abscisse

ordonnee

2.5

?

pt1

abscisse

ordonnee

?

?pt2

abscisse

ordonnee

2.5

?

pt1abscisse

ordonnee

-1.2

?pt2

abscisse

ordonnee

2.5

?

pt1

abscisse

ordonnee

-1.2

?pt2

x1 ?

this

abscisse

ordonnee

2.5

?

pt1abscisse

ordonnee

-1.2

?pt2

x1 2.5

x2 -1.2

Page 34: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 34/199

 

32 

Les  concepts de programmation  Programmation Méthodes d’instance  [email protected] – B227 

Quelles leçons tirer de cette exécution ?-  return retourne le résultat d’une fonction. Puisque par définition une fonction doit retourner un

résultat, tout corps de fonction comporte obligatoirement au moins une instruction  return.A l’inverse, une procédure ne retourne rien et il n’y aura donc  jamais d’instruction return 

dans une procédure. -  Les accolades ({ et }) marquent les limites d’un bloc d’instructions. Ainsi, le contenu d’une

classe est mis entre accolades et le corps des méthodes également.-  L’exécution d’un programme commence par la première ligne de la méthode main  et est

séquentielle mais un appel de méthode court-circuite le fil d’exécution : on déroule le code dela méthode avant de revenir là où on en était.

-  Une méthode d’instance s’appelle toujours sur une instance. Appeler par exemplesetAbscisse sans préciser sur quel Point porte l’appel n’a pas de sens.

-  <obj>.< methode>(<args>)appelle la méthode < methode> de la classe de <obj>  sur

l’objet receveur <obj> avec <args> pour arguments.-  Lors de la déclaration de la méthode les types des paramètres sont précisés. En revanche, on

ne précise pas les types des paramètres lorsqu’on fait appel à une méthode. 

-  Lorsqu’on écrit le code d’une méthode d’instance, le paramètre implicite this désigne l’objetsur lequel est appelée la méthode. On utilise la notation pointée non seulement pour appeler uneméthode sur un objet (cf. ci-dessus) mais aussi pour accéder aux variables d’instance d’un objet.Par exemple, this.abscisse désigne la variable abscisse de l’objet référencé par this.

-  Les arguments sont des variables locales initialisées lors de l’appel avec les valeurs desparamètres effectifs. On parle de  passage par valeur  pour désigner cette façon de passer desarguments à une méthode. Comme pour toutes variables locales, la portée des arguments s’étend

 jusqu’à la fin du bloc dans lequel elles sont déclarées. Les arguments sont donc désalloués de lamémoire dès qu’on sort du corps de la méthode. Ils n’existent pas en dehors de la méthode.

- - - - - - 

On distingue trois types de méthodes : les constructeurs, les accesseurs, et les autres services.- - 

Les  accesseurs  sont des méthodes qui permettent de consulter (on parle de  getter/ accesseur enlecture) ou de modifier ( setter/ accesseur en écriture) l’état d’un objet. Par exemple, getAbscisse estun getter qui permet de consulter l’abscisse d’un Point et setAbscisse est un setter permettant demodifier l’abscisse d’un Point.

- - 

Quel résultat donnerait l’appel d’un getter sur un objet qui n’a pas encore été initialisé ? Oublierd’initialiser est une erreur si fréquente que java systématise l’initialisation des variables d’instance vial’appel obligatoire d’un constructeur lors de la création d’un objet. Vous en déduisez que les

 constructeurs  sont les méthodes qui sont appelées lors de la création d’un objet afin d’initialiserconvenablement son état. Ceci est d’autant plus important que les données sont généralement contraintes

 par des règles de cohérence. Ainsi, que serait une vis à bois avec une longueur nulle ou un diamètrenégatif ? Que serait un horaire avec un nombre de minutes supérieur à 59 comme 4h72 ? Les

constructeurs (et les autres méthodes) devront veiller à la cohérence des données.- - 

On reconnait les constructeurs à leurs signatures car :-  Un constructeur a le nom de la classe pour nom.-  Un constructeur n’a aucun type retour, pas même void .- - 

Soit, mais nous avons pu créer des instances de Point alors que nous n’avons pas encore écris deconstructeur… Si cela est possible c’est parce que si aucun constructeur n’est défini explicitement javafournit un constructeur par défaut qui ne prend aucun argument et qui ne fait rien. Bref, pour l’heure, toutse passe comme si nous avions défini le constructeur suivant :

 public Point( ) {}

Le but d’un constructeur étant d’initialiser l’état de l’objet, un tel constructeur ne peut pas être adéquat

dès lors que la classe possède au moins une variable d’instance. Nous aurons donc presque toujours à

Page 35: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 35/199

Les  concepts de programmation  Programmation Méthodes d’instance  [email protected] – B227 

33 

écrire des constructeurs pour nos classes et ces constructeurs devront veiller à ce que chaquevariable d’instance soit correctement initialisée.

- - 

Ecrivons donc nos premiers constructeurs.

Rajoutez le constructeur Point() et le constructeur Point(double  x, double  y)  puis

complétez la méthode main de sorte que le code de la classe Point soit :1  public class Point {2   private double abscisse;3   private double ordonnee;4 5   public Point( ) {6  this.abscisse = 0.0;7  this.ordonnee = 0.0;8  }9 10   public Point( double x, double y ) {11  this.abscisse = x;12  this.ordonnee = y;

13  }14 15   public double getAbscisse( ) {16  return this.abscisse;17  }18 19   public double getOrdonnee( ) {20  return this.ordonnee;21  }22 23   public void  setAbscisse( double x ) {24  this.abscisse = x;25  }

26 27   public void  setOrdonnee( double y ) {28  this.ordonnee = y;29  }30 31   public static void  main(String[] args) {32  Point pt1 = new Point( );33  Point pt2 = new Point(-1.2, 7.4);34  double x1 = pt1.getAbscisse( ) ;35  double x2 = pt2.getAbscisse( ) ;36  System.out.println(x1);37  System.out.println(x2);38  }

39  } - - - 

 Nous avons à présent deux constructeurs qui tous deux initialisent chaque variable d’instance. La ligne24 de main exploite le premier constructeur. L’opérateur new crée une instance de Point puis appellele constructeur sans paramètre qui fixe à 0.0  les coordonnées du point. La ligne 25  précise deux

 paramètres effectifs (-1.2 et 7.4) lors de la création de la seconde instance de Point et c’est donc lesecond constructeur qui est appelé. Les lignes 28 et 29 affichent donc respectivement 0.0 et -1.2.

Au passage, notons qu’il est possible d’avoir plusieurs méthodes qui portent le même nom pour peuqu’elles diffèrent suffisamment (en type et/ou en nombre) au niveau de leurs arguments. On parle alors de

 surcharge de méthode. Java déterminera la méthode à appeler en fonction des paramètres fournis. Ici iln’y a aucune ambigüité possible puisque les deux constructeurs n’ont pas le même nombre de paramètres.

Page 36: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 36/199

 

34 

Les  concepts de programmation  Programmation Méthodes d’instance  [email protected] – B227 

Les  autres services  désignent toutes les méthodes d’instance qui ne sont ni des accesseurs ni desconstructeurs. Par exemple, pour la classe Point, on peut songer à une méthode permettant de connaitrela distance séparant un point d’un autre (la classe Math  regroupe un tas de fonctions mathématiquescomme Math.sqrt qui retourne la racine carrée d’un nombre) :

 public double distance( Point pt) {// retourne la distance separant l'objet receveur de pt.

double deltaX = pt.getAbscisse() - this.getAbscisse();double deltaY = pt.getOrdonnee() - this.getOrdonnee();return Math.sqrt( (deltaX*deltaX)+(deltaY*deltaY) );

}

Résumé-  On déclare une méthode au sein d’une classe en fournissant sa signature/en-tête et son corps :

<visu> <tRetour> <nomMethode>(<tArg1> <nomArg1>,…,<tArgN> <nomArgN>){<corps>

}

-  <nomArg1>,… <nomArgN>  sont les  paramètres formels  de la méthode, c’est-à-dire les noms

utilisés dans le corps de la méthode pour désigner les données fournies lors de l’appel. Ce sont desvariables locales, créées lors de l’appel et dont la portée est limitée à la méthode.

-  Une fois définie, une méthode peut-être appelée à divers endroits du programme. Une  méthode

 d’instance (donc non static) d’une classe C est toujours appelée sur une instance de type C :<obj>.< methode>(<args>) ; 

-  Toute méthode d’instance d’une classe C  a un paramètre implicite nommé this  référençantl’objet sur lequel est appelée la méthode (l’ objet receveur).

-  Les arguments précisés lors d’un appel sont appelés paramètres effectifs.-  On précise les types des paramètres lors de la définition d’une méthode, mais on ne précise jamais

les types des paramètres lors de l’appel d’une méthode.-  Lors d’un appel l’exécution fait un saut jusqu’au code de la méthode. L’espace pour les

 paramètres formels est alloué et les valeurs des paramètres effectifs sont recopiées dans les paramètres formels. Le code de la méthode est ensuite déroulé et une fois la méthode achevéel’exécution reprend à l’endroit de l’appel.

-  Une méthode est une fonction si elle retourne un résultat. Sinon, elle est une procédure et a void   pour type retour.

-  L’instruction return x ; termine l’exécution d’une fonction en fournissant x pour résultat.-  Le corps d’une fonction comporte au moins une instruction return. Le corps d’une procédure ne

contient jamais d’instruction return.-  Une méthode d’instance peut être un  accesseur en lecture  ( getter) auquel cas elle permet de

consulter une donnée de l’objet (généralement une partie de son état). Elle peut également être un accesseur en écriture ( setter), c'est-à-dire une méthode modifiant l’état de l’objet, ou encore êtreun constructeur, appelé lors de la création d’un objet afin d’initialiser convenablement toutes les

variables d’instance. Enfin, on parle « d’ autres services » pour désigner les méthodes qui ne sontni des constructeurs, ni des accesseurs.

-  Un constructeur a le nom de la classe pour nom et n’a aucun type retour, pas même void .-  Dans une classe, on peut avoir plusieurs méthodes portant le même nom mais ces méthodes

doivent alors avoir des arguments suffisamment différents (par leur nombre et/ou types) car lorsd’un appel c’est via les types des paramètres que la détermination de la méthode s’effectuera alors.

Exercice PR004 p. 154  Corrigé p. 176 

Page 37: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 37/199

Les  concepts de programmation  Programmation La classe String  [email protected] – B227 

35 

3.7.  La classe String 

Dans la section 3.4.3 nous avons vu les types primitifs (int, double, char, …) et des valeurslittérales pour ces types ('a'  est de type char, 54321  de type int, …) mais nous n’avons pas vu

comment représenter du texte (char ne permet de mémoriser qu’un seul caractère).Les portions de texte sont appelées des  chaînes de caractères. Nous n’avons pas abordé leur cas dans

la section 3.4.3 parce qu’elles ne sont pas représentées par un type primitif, mais par la classe String. Notez le S  majuscule à String  pour bien marquer qu’il s’agit d’une classe. Vous avez en fait déjàutilisé une chaîne de caractères puisque dans notre programme minimaliste nous avions utilisél’instruction System.out.println("coucou !")  pour afficher le message coucou !. Les

guillemets " délimitent les valeurs littérales de type String. Tout ce qui se trouve entre deuxguillemets n’est pas évalué mais est considéré comme une chaîne de caractères. L’instructionSystem.out.println((2+7)*3)affichera 27  (l’expression (2+7)*3  est évaluée et c’est lerésultat de cette évaluation qui est ensuite affiché) alors que l’instructionSystem.out.println("(2+7)*3")affichera (2+7)*3 (on demande d’afficher la chaîne de

caractères "(2+7)*3").Si vous avez bien suivi les sections précédentes, vous devez savoir que si on déclare une variable

d’instance de type String, alors on est en train de déclarer une référence, puisque les variablesd’instance qui ne sont pas de type primitif sont des références. Cela signifie que la variable d’instance nestockera pas directement l’information, mais elle contiendra l’adresse de l’objet mémorisantl’information. Prenons l’exemple d’un programme portant sur des élèves représentés par un prénom, unnom et une moyenne générale.

Exemple : fichier Eleve.java

 public class Eleve {

 private String prenom, nom; private double moyenne;

 public Eleve(String p, String n, double m) {this.prenom = p;this.nom = n;this.moyenne = m;

}

 public static void  main(String[] args) {Eleve alain = new Eleve("Alain", "Le blanc", 13.5);

}}

L’occupation mémoire à la fin du main de ce programme incomplet peut être schématisé par :

Les variables d’instance prenom et nom sont des références qui contiennent les adresses des chaînesde caractères correspondant au prénom et au nom de l’élève.

Comment sont représentées en mémoire les objets de type String? On n’a pas besoin de le savoir.La classe String précise des variables d’instance mais nous n’avons pas besoin de les connaître pourmanipuler des chaînes de caractères. Tout ce qui nous importe c’est les méthodes de la classe String 

prenom "Alain"

nom

moyenne 13.5

"Le blanc"

alain

Page 38: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 38/199

 

36 

Les  concepts de programmation  Programmation La classe String  [email protected] – B227 

afin de savoir ce qu’il est possible de faire sur une instance de String. C’est comme pour les types primitifs : on n’a pas besoin de savoir comment java utilise les 64 bits d’un double pour représenter unnombre à virgule, l’important c’est de savoir qu’on dispose de l’addition, de la multiplication, de ladivision, … C’est le principe d’encapsulation, sur lequel nous reviendrons, à savoir que pour pouvoirmanipuler des objets d’une classe nous n’avons pas à connaître les variables d’instance, pas plus que le

code des méthodes. Il suffit de connaître les méthodes disponibles et leurs spécifications (la descriptionde ce qu’elles font).

Un tas de classes sont fournies avec java et pour chacune d’elles une documentation est fournie. Cettedocumentation, appelée javadoc, est générée automatiquement à partir des commentaires mis dans laclasse (nous les avons mentionnés en section 3.2 et nous les aborderons plus tard). L’ensemble des cesdocumentions forment l’ API   (Application Programming Interface) qu’on trouve à l’adressehttp://docs.oracle.com/javase/7/docs/api/

On retrouve facilement la javadoc d’une classe en tapant dans un moteur de recherche « javanom_Classe ».

Recherchez « java string » sur internet puis cliquez sur la page d’oracle. La javadoc commence par une description de la classe, la liste des constructeurs disponibles et la description courte dechacune des méthodes de la classe dont voici le début :

Si vous cliquez sur le nom d’une méthode, par exemple charAt, votre navigateur internet vousmontre la description détaillée de cette méthode.

Il n’est bien sûr pas indispensable de connaître par cœur les spécifications des 80 méthodes de cetteclasse puisque vous pourrez toujours vous reporter à cette documentation. Toutefois, String  est uneclasse très utilisée et il convient de connaître quelques-uns des principaux services offerts par cette classe.

Page 39: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 39/199

Les  concepts de programmation  Programmation La classe String  [email protected] – B227 

37 

Ci-dessous s1 et s2 désignent des String, i est un entier de [0, s1.length()[ et j un entierde [i, s1.length()].En-tête Descriptions1.length() Retourne la longueur de la chaîne, donc le nombre de caractères qui la

compose.Ex. : s1.length vaut la longueur de s1.

s1.charAt(i)

avec i[0, s1.length()[ Retourne le caractère d’index i. Les index commençant à 0, c’est donc lecaractère de rang (i+1) qui est retourné. Attention au fait que i doit êtrecompris entre 0 (inclus) et la taille de la chaine (exclue).Ex. : s1.charAt(0)  retourne le 1er   caractère de s1, s1.charAt(1) retourne le 2ème,…

s1.compareTo(s2) Retourne 0 si s1 est égale à s2, un nombre négative si s1 vient avant s2 dans l’ordre lexicographique (l’ordre du dictionnaire) et un nombre positifsi s1 vient après s2 dans l’ordre lexicographique

s1.equals(s2) Retourne true si s1 et s2 sont des chaînes égales entre elles (même suitede caractères), et retourne false dans le cas contraire.

s1.indexOf(s2)  Retourne l’index de la première occurrence de s2 dans s1 (retourne -1 sile paramètre n’apparaît pas dans l’objet receveur).Ex. : si s1 vaut "et comment va coco ?", s1.indexOf("co")  retourne 3, s1.indexOf("coco")   retourne 14  ets1.indexOf("quand") retourne -1.

s1.replace("to","ti") Retourne une nouvelle chaîne correspondant à s1 dans laquelle toutes lesoccurrences de "to" ont été remplacées par "ti".

s1.replaceFirst("to","ti") Retourne une nouvelle chaîne correspondant à s1 dans laquelle la premièreoccurrence de "to" a été remplacée par "ti".

s1.substring(i,j)  Retourne une chaîne composée des caractères dont l’index fait partie de[i, j[. 

Ex. : si s1 vaut "Bonjour", s1.subString(3,6)  vaut "jou".s1.toLowerCase()  Retourne une instance de String correspondant à la chaine en minuscules.Ex. : si s1 vaut "BoNjOuR", s1.toLowerCase()  vaut "bonjour".

s1.toUpperCase() Retourne une instance de String correspondant à la chaine en majuscules.Ex. : si s1 vaut "BoNjOuR", s1.toUpperCase()  vaut "BONJOUR".

Il ne s’agit que d’une sélection, vous serez amenés à utiliser d’autres services comme split.

En plus des services listés dans la javadoc de la classe String, un opérateur ( +  ) permet laconcaténation de deux chaînes de caractères. Ainsi, "j’aime"+"  programmer"  est une nouvellechaîne formée par juxtaposition de "j’aime" et " programmer" (donc "j’aime programmer").

Résumé-  Les chaînes de caractères sont des bouts de texte représentés par la classe String.-  String  n’étant pas un type primitif mais une classe, les variables de type String  sont des

références.-  Les valeurs littérales des chaînes de caractères sont placées entre guillemets. Ex. : "Bonjour". -  L’API de java qui regroupe les documentations de toutes les classes fournies est disponible à

l’adresse http://docs.oracle.com/javase/7/docs/api/.-  Si s  est une String, alors s.length()  est sa longueur et s.charAt( i )  avec

i[0, s.length()[  est son caractère d’index i  (son (i+1)ème  caractère vu que les indexcommencent à 0).

-  Si s1  et s2  sont deux String, alors s1+s2  est la concaténation de s1  et s2, c’est-à-dire la

chaîne formée par juxtaposition de s1 et s2.

Page 40: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 40/199

 

38 

Les  concepts de programmation  Programmation Conversions implicites et explicites  [email protected] – B227 

3.8.  Conversions implicites et explicites

3.8.1.  Conversion implicite / promotion

Lorsque vous avez consulté le mémento vous avez du voir qu’il y avait les opérateurs +, -, * et / dedéfinis à la fois pour les entiers et les nombres à virgule. Si les deux opérandes sont entières, / est la

division euclidienne.  Ainsi, 10/4  vaut 2  alors que 10.0/4.0  vaut 2.5. Si les opérandes sont de

types numériques différents, il y a conversion implicite vers le type le plus précis  afin de limiter la perte de précision. Si on écrit 10/4.0, 10  sera implicitement converti en double (10.0) avant d’êtredivisé par 4.0 et le résultat sera 2.5.

L’ordinateur dispose de plus d’une table de correspondance (la table ASCII) entre les caractères(char) et les entiers. Dès lors, java est capable de passer de char à int et vice versa. Dans cette table(qu’il n’est clairement pas nécessaire d’apprendre) les caractères de l’alphabet ont des codes consécutifs :'a' est codé par 97, 'b' par 98, 'c' par 99 et 'z' par 122 ('A' par 65, 'B' par 66, …).

Enfin, pour convertir une expression d’un type primitif en String, le plus simple est de la concaténer àla chaîne vide. En effet, si par exemple on écrit 2.5+"", java va devoir convertir 2.5 en une String avant de pouvoir faire la concaténation avec "". Et 2.5+"" vaut au final "2.5".

Donc, si x  est une variable d’un type primitif, alors x+""  est la chaîne de caractères

correspondant à sa valeur. Si par exemple x est un boolean valant true, ""+x vaut "true", et si x est l’entier -1, alors ""+x vaut "-1".

Attention : on ne convertit pas en String en rajoutant des guillemets autour de la variable ! "x" est la chaîne composée du seul caractère x (pas la valeur de x).

Exemple public class TestConversions {

 public static void main(String[] args) { 

int i = 123;System.out.println("i="+i);System.out.println("5/2="+(5/2)+" et 5.0/2="+(5.0/2));int codeA = 'A';char dixiemeLettre = 'A'+9;char caractere70 = (char)70;System.out.println(codeA+" "+dixiemeLettre+" "+caractere70);

}}

Affichage produit :i=1235/2=2 et 5.0/2=2.565 J F 

Page 41: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 41/199

Les  concepts de programmation  Programmation Conversions implicites et explicites  [email protected] – B227 

39 

3.8.2.  toString()

On vient de voir ce que donne la concaténation d’une expression de type primitif avec une String,mais qu’arrive-t-il si l’expression est de type Objet ? Testons.

Rajoutez à la méthode main  de votre classe Point  l’instructionSystem.out.println("pt2="+pt2); puis exécutez. 

Vous devriez voir s’afficher une ligne du type pt2=Point@b8df17 .

Lorsqu’un objet doit être converti en  String, sa méthode  String toString( )  est

implicitement appelée sur lui.  Tout se passe comme si nous avions écris l’instructionSystem.out.println("pt2="+pt2.toString());. Nous aurions d’ailleurs pu préciserexplicitement l’appel à toString()sur pt2. 

Soit, mais nous n’avons pas défini de telle méthode dans notre classe Point !

Si cela ne pose pas de problème c’est parce que toutes les classes ont par défaut une méthodetoString()  qui retourne la chaîne correspondant à l’adresse de l’objet. Ce qui explique l’affichage

 produit, Point@b8df17 étant la valeur de la référence pt2, l’adresse du point désigné par pt2.

Reste que cette version par défaut correspond très rarement à ce que nous souhaiterions. Dès lors,nous prendrons l’habitude de redéfinir la méthode toString() de nos classes. Pour Point  parexemple, il serait souhaitable d’obtenir une chaîne indiquant les coordonnées du point entre parenthèses.

Rajoutez dans la classe Point le service : public String toString() {

return "("+this.getAbscisse()+", "+this.getOrdonnee()+")";}

 puis exécutez. 

Vous devriez voir s’afficher  pt2=(-1.2, 7.4).

Attention à ne pas confondre toString()  avec une procédure d’affichage. toString()  estune fonction qui retourne une chaîne de caractères. Seule, elle ne produit pas d’affichage. Ainsi, si dansvotre main vous ajoutez une ligne pt1.toString();  il n’y aura pas d’erreur, mais il n’y aura pasd’affichage de pt1. Cette instruction permet d’obtenir la chaîne "(0.0, 0.0)"  mais nous n’enfaisons rien, et en particulier nous ne l’affichons pas via un appel à System.out.println.

3.8.3.  Conversion explicite / Casting / Coercition / Transtypage

Il est possible de convertir la valeur d’une expression dans un autre type de base en préfixant cette

expression du type entre parenthèses (les parenthèses autour du type sont indispensables). Parexemple, (int)(10.0/4.0) est l’entier 2 (2.5 converti en int). Bien sûr, toutes les conversions nesont pas possibles. Par exemple, on ne peut pas convertir un caractère en Booléen, ça n’a pas de sens.

3.8.4.  Conversion des chaînes de caractères

On peut convertir une String s dont la valeur correspond à un entier (resp. un nombre à virgule ouun Booléen) en un int  (resp. double  ou boolean) via l’appel Integer.parseInt(s)  (resp.Double.parseDouble(s)  ou Boolean.parseBoolean(s)). Par exemple, si s  vaut "1234" alors Integer.parseInt(s) vaut 1234.

Attention ! Le paramètre doit pouvoir être converti. Si s  vaut "toto", l’appelInteger.parseInt(s) interrompra le programme.

Page 42: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 42/199

 

40 

Les  concepts de programmation  Programmation Conversions implicites et explicites  [email protected] – B227 

Résumé-  Les conversions implicites de java concernant les valeurs numériques vont toujours vers le type le

 plus précis afin de limiter les pertes de précisions. Par exemple, (5.0 / 2) vaut 2.5 (dès lors

qu’un opérande est un double, l’autre est convertie en double, ici 2 est converti en 2.0) alorsque (5/2) vaut 2 (deux opérandes entières division euclidienne).-  Une table permet à java de convertir les char en int et vice-versa. Par exemple, code vaut 65 

après l’instruction int code='A' ; -  si x est d’un type primitif, alors x+"" est la String correspondant à sa valeur.-  on ne convertit pas une expression en String  en rajoutant des guillemets autour d’elle. Par

exemple, si x est une variable valant 123, alors "x" vaut "x" et pas "123".-  Lorsqu’un objet doit être converti en String, sa méthode String toString( )  est

implicitement appelée sur lui.-  Toute classe a par défaut une méthode toString()  renvoyant une chaîne correspondant à

l’adresse de l’objet receveur. Nous prendrons l’habitude de redéfinir la méthode toString().

-  On peut explicitement convertir en un autre type en préfixant par le type désiré entre parenthèses(les parenthèses autour du type sont indispensables). Par exemple, (int)x est l’entiercorrespondant à x. Bien sûr, cela ne fonctionne que pour des types compatibles (un entier en unrationnel, un char en int, … mais pas un int en boolean par exemple).

-  Les fonctions Integer.parseInt(String s), Double.parseDouble(String s)et Boolean.parseBoolean(String s) permettent de convertir une chaîne de caractère enrespectivement un int, un double  et un boolean, pour peu que s  corresponde bien à unevaleur du type visé (Integer.parseInt("toto") interrompra le programme).

Exercice PR005 p. 155  Corrigé p. 176 

Page 43: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 43/199

Les  concepts de programmation  Programmation Entrées / Sorties  [email protected] – B227 

41 

3.9.  Entrées / Sorties

Si la majeure partie du code que nous écrirons consistera à traiter des données en mémoire, une partieessentielle est l’acquisition des données initiales via des opérations d’entrée (saisie au clavier, clic desouris, lecture d’un fichier, …) et la réalisation d’opérations de sortie (affichage à l’écran, impression,

sauvegarde dans un fichier, envoi d’un fax, …). Dans un premier temps, notre seule opération d’entréesera la saisie d’informations au clavier et notre seule opération de sortie sera l’affichage à l’écran. NosIHM (Interfaces Homme/Machine, les partie de programme responsables des entrées/sorties) seront donc

 pour l’heure textuelles.

3.9.1.  Afficher

Vous avez déjà utilisé System.out.println pour afficher des messages sur la console, mais nousn’avons pas détaillé cette instruction. System.out (avec un S majuscule) désigne la sortie standard dusystème, laquelle est l’écran par défaut. Deux variantes, System.out.println(<exp>)  et System.out.print(<exp>), affichent le texte correspondant au paramètre sur la console. La seule

différence réside dans le fait que println passe à la ligne après cet affichage, chose que ne fait pasprint.

Si on précise une référence en guise de paramètre, la méthode toString() est appelée sur l’objetréférencé afin de connaître la chaîne de caractères à afficher.

Rappelons que les séquences de caractères \t  et \n  provoquent respectivement un passage à la prochaine tabulation et un passage à la ligne. De plus, si l’on souhaite qu’une chaîne de caractèrescomporte un guillemet (resp. le caractère \) il faut utiliser la séquence \" (resp. \\).

Enfin, comme nous avons pu le voir, le raccourci clavier pour System.out.println  dansl’éditeur d’eclipse est sysou [Ctrl]+[Espace] .

Exemples public class TestAffichage {

 public static void  main(String[] args) {System.out.println("La factorielle de 5 est "+(2*3*4*5));System.out.println("On m'appelle \"Romu\"");System.out.println("1\t2\t3\n2\n3");

}}

Affichage produit :La factorielle de 5 est 120On m’appelle "Romu"1 2 323 

3.9.2.  Effectuer une saisie au clavier

De manière similaire, System.in désigne l’entrée standard, à savoir le clavier, mais son exploitationest moins directe. Une solution passe la création d’une instance de la classe Scanner avec System.in 

 pour paramètre puis d’utiliser les méthodes de cette classe. Hélas, les méthodes de Scanner peuventinterrompre brutalement votre programme si d’aventure l’utilisateur fait une erreur de frappe (si parexemple il tape du texte alors que vous demandiez un entier).

Un fichier nommé Clavier.java  vous est fourni sur campus. Il contient des fonctions (int lireInt(), long lireLong(), float lireFloat(), double lireDouble(), String

Page 44: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 44/199

 

42 

Les  concepts de programmation  Programmation Entrées / Sorties  [email protected] – B227 

lireString() et char lireChar()) permettant de lire des informations (respectivement un int,un long, un float, un double, une String ou un char) au clavier. Pour utiliser ces fonctions, lefichier Clavier.java doit être placé dans le même répertoire que votre code source. Pour cela, reportez-vous à la section 7.1 page 123.

Lors d’un appel à Clavier.lireInt(); par exemple, le programme est placé en attente d’unesaisie. L’utilisateur devra taper un nombre et dès qu’il aura appuyé sur la touche entrée la fonctionClavier.lireInt() retournera l’entier qui a été saisi. Si la saisie ne correspond pas au type attendu(ex. : "toto"  alors qu’on attend un double) la valeur retournée est la plus grande représentable(2147483647  pour lireInt(), 9223372036854775807   pour lireLong(), …).  Notez que lesfonctions de saisie (y compris lireChar ()) ne retournent une valeur qu’une fois la touche entréeenfoncée.

Exemple

 public class Saluer { public static void main(String[] args) {

// Sortie : Affiche un message invitant à indiquer un prénom, saisit le

// prénom puis affiche un message saluant personnellement.System.out.println("Quel est votre prénom ?") ;String prenom = Clavier.lireString() ;System.out.println("Bonjour "+prenom ) ;

}}

Vous remarquerez que les saisies sont généralement précédées d’un affichage afin de préciser àl’utilisateur ce qu’il doit saisir.

Sous eclipse la saisie s’effectue dans la console. Si le curseur est dans l’éditeur, vos saisies au claviers’afficheront dans l’éditeur. Il faut cliquer une première fois dans la console afin de lui donner le focus etainsi effectuer des saisies.

Résumé-  System.out.println(<exp>)  permet d’afficher le texte correspondant à la valeur de

<exp>. Si <exp>  est une référence, la chaîne affichée est la valeur retournée par l’appel detoString() sur l’objet référencé.

-  Afficher la séquence de caractères \n (resp. \t, \\ et \") provoque un passage à la ligne (resp.un passage à la tabulation suivante, l’affichage du caractère \ et l’affichage du caractère ").

-  System.out.println(<exp>) est équivalent à System.out.print(<exp>+"\n").-  int  Clavier.lireInt()  (resp. long  Clavier.lireLong(), float 

Clavier.lireFloat(), double  Clavier.lireDouble(), StringClavier.lireString()  et char Clavier.lireChar()) est une fonction permettantde réaliser la saisie d’un int (resp. long, float, double, String et char). Pour pouvoirutiliser ces fonctions le fichier Clavier.java doit avoir été ajouté parmi les sources du programme.

Exercice PR006 p. 156  Corrigé p. 176 

Page 45: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 45/199

Les  concepts de programmation  Programmation Egalité  [email protected] – B227

 

43 

3.10.  Egalité

Vous avez peut-être remarqué dans le mémento que == (Ne pas confondre avec l’affectation =) est unopérateur permettant de tester l’égalité. x==y  vaut true  si x  et y  ont même valeur (et vaut false sinon). Tâchez de deviner ce qu’affiche la procédure principale suivante.

1  public class TestEgalite {2  public static void  main(String[] args) {3 double x = 2.0;4 double y = 3.0;5 Point pt1 = new Point(x,y);6 Point pt2 = new Point(x,y);7 Point pt3 = pt1 ;8 System.out.println(x==2.0);9 System.out.println(x+1.0==y);10 System.out.println(pt1==pt2);11 System.out.println(pt1==pt3);12 }

13 } 

Comme vous l’avez surement deviné, les lignes 8 et 9 affichent toutes deux true. La ligne 10 peutdavantage porter à confusion. Quelle est la valeur de pt1 ? L’adresse du point créé à la ligne 5. Et quevaut pt2 ? L’adresse du point créé à la ligne 6. pt1 et pt2 ne contiennent donc pas les mêmes adresseset leurs valeurs sont donc différentes, ce qui provoque l’affichage de false par la ligne 10.

pt1  et pt2 étant des références, (pt1==pt2)  vaut true  si ces deux références contiennent lamême adresse, donc si elles désignent la même instance de point, ce qui n’est pas le cas. Par contre, pt1 et pt3 contiennent toutes deux l’adresse du premier point et la ligne 11 conduit donc à l’affichage detrue.

Placé entre deux références==

 évalue donc si les deux références désignent le même objet. Maiscomment tester l’égalité des objets ? Nous aimerions pouvoir vérifier par exemple si les deux points

désignés respectivement par pt1 et pt2 ont des états égaux. Ne pas vérifier que les références désignenttoutes deux le même objet comme le fait ==, mais deux objets qui ont la même valeur.

Souvenez vous de la méthode toString(). Nous avions vu que par défaut tout objet en avait une,mais que celle fournie par défaut n’avait pas le comportement voulu et que nous redéfinirons doncsystématiquement cette méthode dans nos classes. Si chaque objet en a une par défaut c’est qu’en javatoute classe est un sous-type de la classe Object, et la classe Object  possède une méthodetoString(). La seconde méthode qui va nous intéresser dans la classe Object  est boolean equals(Object), celle-là même qui va nous servir à comparer deux objets entre eux.

Toute classe a donc par défaut la méthode equals de la classe Object mais là encore le comportement

n’est pas celui attendu et comme pour la méthode toString() nous devrons la redéfinir. En effet, leequals  de la classe Object  teste si les références sont égales et est donc équivalent à ==. Nous

aurons donc à la redéfinir afin qu’elle teste cette fois l’égalité des objets .

 Nous pourrions vouloir définir la méthode equals de la classe Point via la déclaration suivante :

1   public  boolean equals(Object o) {2  return ( this.getAbscisse()==o.getAbscisse() )3  && ( this.getOrdonnee()==o.getOrdonnee() );4  } 

L’expression retournée ne vaut true que si l’objet receveur this et l’objet passé en paramètre o ontla même abscisse et (&& est le « et Booléen ») la même ordonnée. Toutefois, comme indiqué, il y a une

erreur. S’agissant d’une méthode d’instance de la classe Point, this  est de type Point  et on peutfaire appel à getAbscisse() et getOrdonnee() sur this. Par contre, o est de type Object et on

Page 46: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 46/199

 

44 

Les  concepts de programmation  Programmation Egalité  [email protected] – B227 

ne peut donc pas appliquer ces méthodes sur o. Toute classe est un sous-type de Object, donc laréférence o peut référencer n’importe quel type d’objet. o peut désigner un Point mais peut tout autantdésigner une vis, une glace, ou tout autre type imaginable. Si nous avons l’assurance que o désigne unPoint, nous pourrions écrire le code suivant :

1  public  boolean equals(Object o) {2 return ( this.getAbscisse()==((Point)o).getAbscisse() )3 && ( this.getOrdonnee()==((Point)o).getOrdonnee() );4 } 

Le casting de o  en Point  force à considérer o  comme une référence vers un Point  et l’appel àgetAbscisse() est dès lors possible. Il n’y a plus d’erreur détectée à la compilation, mais une erreursurviendra si d’aventure on appelle la méthode equals en passant en paramètre un objet qui n’est pas detype Point. Pour éviter ce problème il nous faut nous assurer que o est de type Point (ce que permetde faire l’opérateur instanceof) avant de faire appel aux méthodes getAbscisse()  etgetOrdonnee().

1  public  boolean equals(Object o) {2 return (o instanceof Point)3 && ( this.getAbscisse()==((Point)o).getAbscisse() )4 && ( this.getOrdonnee()==((Point)o).getOrdonnee() );5 } 

 Notez que l’évaluation d’une expression de type (X && Y)  est dite  paresseuse  : java évalue toutd’abord X et si X vaut false, Y n’est même pas évaluée puisque (X&&Y) vaut forcément false si X vaut false. Il en va de même pour les expressions de type (X||Y) : X est d’abord évaluée et si X vauttrue Y n’est pas évaluée puisque (X||Y) vaut forcément true si X vaut true.

L’ordre a donc de l’importance : on teste tout d’abord si o est de type Point et ce n’est que si c’est le

cas qu’on teste si o a les mêmes coordonnées que l’objet receveur. Notez que la notion d’égalité est à voir de toute façon au cas par cas. Si dans la majorité des cas il

s’agit de vérifier si les deux objets ont des états identiques, il ne s’agit pas d’une règle absolue. Parexemple, si on souhaite modéliser des températures, nous ne vérifierons surement pas l’égalité absoluemais à un delta près correspondant à la précision des appareils de mesure. Pour des voitures représentées

 par un modèle, une couleur, une puissance et un numéro d’immatriculation, on pourrait vouloir préciserque l’égalité correspond à avoir le même modèle et la même puissance mais potentiellement pas la mêmecouleur et le même numéro d’immatriculation (comme lorsqu’on dit « j’ai la même en rouge »).

Résumé-  Si A et B sont deux expressions de type primitif alors A==B permet de tester leur égalité.-  Si A et B sont deux références alors A==B permet de tester si elles désignent le même objet.

-  Si A et B sont deux références alors A.equals(B) permet de tester si l’objet désigné par A estégal à l’objet désigné par B.

-  Dans nos classes nous aurons à redéfinir la méthode public  boolean  equals(Object o) afin d’exprimer ce à quoi correspond l’égalité pour ces classes.

-  (o instanceof A) vaut true si et seulement si o désigne un objet de type A.-  L’évaluation des opérateurs && et || est dite paresseuse. Lors de l’évaluation de (A&&B), java

teste tout d’abord A et ne teste la valeur de B que si A vaut true (car si A vaut false A&&B vaut de toute façon false, quelle que soit la valeur de B). De manière similaire, lors del’évaluation de (A||B), java teste tout d’abord A et ne teste la valeur de B que si A vaut false (car si A vaut true  (A||B) vaut de toute façon true, quelle que soit la valeur de B).

Exercice PR007

 p.

 157

 Corrigé

 p.

 176

 

Page 47: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 47/199

Les  concepts de programmation  Programmation L’alternative / Conditionnelle simple  [email protected] – B227 

45 

3.11.  L’alternative / Conditionnelle simple

Pour l’heure, nous ne pouvons pas donner d’ordre conditionné. Nous rencontrons fréquemment de telsordres dans la vie courant : « si votre véhicule dépasse les 4,5 tonnes passez à gauche sinon passez àdroite », « si la pointe de votre couteau ressort nette du gâteau alors arrêtez la cuisson », …

Cette lacune est comblée par notre nouvelle règle de grammaire dont la syntaxe est la suivante.if (<condition>) { if (<condition>) {

<blocSi>  <blocSi> } ou }else {

<blocSinon> } 

L’alternative if  (<condition>) {<blocSi>} else  {<blocSinon>}  conditionnel’exécution du bloc d’instruction <blocSi>  au fait que <condition>  vaille true. Si la conditionn’est pas vérifiée (si elle vaut false) c’est <blocSinon>  qui sera exécutée. L’alternative peut selimiter à if

 (<condition>) {<blocSi>} si aucun traitement particulier n’est à effectuer dans le

cas où la condition n’est pas vérifiée.

Condition doit être une expression à valeur booléenne. Le plus souvent il s’agit donc d’un testd’égalité (==), d’infériorité/supériorité (stricte (< ou >) ou non (<= ou >=)) ou encore de différence (!=).Mais il peut s’agir également d’une variable Booléenne ou d’un appel à une fonction ayant boolean 

 pour type retour.

ExemplePour la classe VisABois nous pourrions définir la méthode toString() ci-dessous:  public String toString() { // Sortie : Retourne une chaine correspondant a l’etat de la vis.

// Ex.: retourne "Cruci-40x5" pour une vis a tête cruciforme de 40 de

// long et 5 de diametre.

String s;if (this.getCruciforme()) {

s = "Cruci-";}else {

s = "Plate-";}return s+this.getLongueur()+"x"+this.getDiametre();

}

Erreurs classiques 

-  Oublier les parenthèses autour de la condition. Ces parenthèses sont obligatoires.-  Oublier les accolades. Si le bloc se résume à une seule instruction il est possible de ne pasmentionner d’accolades mais l’oubli d’accolades est une erreur si fréquente qu’il est vivementconseillé de mettre systématiquement des accolades autour des blocs.

-  Précisez =  au lieu de == dans la condition. =  est l’affectation alors que ==  est le test d’égalitéentre des expressions de type de base.

-  Le caractère exclusif du else.

Dans le cas à gauche, <blocB> sera exécuté systématiquement, que la condition soit vérifiée ou non,alors que dans le cas de droite le <blocB> ne sera exécuté que si la condition est fausse.

if (<condition>) { <blocA>

}<blocB>

if (<condition>) { <blocA>

}else { 

<blocB>} 

Page 48: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 48/199

 

46 

Les  concepts de programmation  Programmation L’alternative / Conditionnelle simple  [email protected] – B227 

Dans le cas à droite, selon la valeur de la condition on exécutera soit le <blocA> soit le <blocB> mais jamais les deux blocs. Dans le cas de gauche, si la condition est initialement vraie on va exécuter le<blocA> et si ce bloc modifie des variables intervenant dans la condition il se peut que l’exécution du<blocA> rende la condition fausse. On exécutera alors également le <blocB>.

Lisibilité  

Au-delà des erreurs, une maîtrise imparfaite du concept de conditionnelle peut conduire à des schémasd’utilisation peu lisibles.

La condition (!<condition>) est forcément vérifiée au niveau de la clause else et il est doncinutile de la tester.

Par définition de la conditionnelle, l’exécution de <blocA>  ne se fait que si <condition> vauttrue. Rajouter ==true est totalement inutile. C’est vouloir exprimer « ne faire <blocA> que si il estvrai que <condition> est vrai », ce qui est équivalent, mais plus lourd que de simplement dire « ne

faire <blocA> que si <condition> est vraie ».

Il n’y a rien à faire si <condition>  est vrai. Il n’y a une tâche à réaliser (<blocA>) que si lacondition n’est pas vérifiée. Autant le faire ressortir à l’aide de la négation ( ! ) et en se passant du else.

if (<condition>) { <blocA>

}if (!<condition>) { 

<blocB>} 

if (<condition>) { <blocA>

}else { 

<blocB>} 

if (<condition>) { <blocA>

}else {

if (!<condition>) {<blocB>

if (<condition>) { <blocA>

}else {

<blocB>}

 

version davantage lisible 

if (<condition>==true) { <blocA>

}

if (<condition>) { <blocA>

}

version davanta e lisible 

if (<condition>) { // rien… bloc vide 

}else {

<blocA>} 

if (!<condition>) { <blocA>

}

version davantage lisible 

Page 49: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 49/199

Les  concepts de programmation  Programmation L’alternative / Conditionnelle simple  [email protected] – B227 

47 

Dans le schéma ci-dessus, <blocA>  est exécuté systématiquement après <blocB>  ou <blocC>.L’exécution de <blocA> est indépendante de la condition et il vaut mieux par conséquent la mentionneren dehors de la conditionnelle pour que le lecteur puisse bien voir que seules les exécutions des blocs<blocB> et <blocC> dépendent de la condition. La duplication (comme dans la figure de gauche oùl’on a écrit <blocA>  en deux exemplaires) peut également conduire à davantage d’erreurs : si on acommis une erreur dans <blocA>  l’erreur sera dupliquée. Il peut également y avoir une recopieimparfaite avec oubli d’une instruction importante par exemple. La duplication est donc à éviter.

On ne fait <blocA>  que si à la fois <cond1> et <cond2> sont vraies, donc autant l’exprimerexplicitement.

On exécute <blocA>  si au moins une des deux conditions est vraie. Autant exprimer celaexplicitement, d’autant que ça évite de dupliquer du code, et donc minimise le risque d’erreurs.

On affecte true  à maVariable  si <condition>  vaut true  et on lui affecte false  si<condition>  vaut false : on ne fait rien d’autre qu’affecter la valeur de <condition>  àmaVariable. Remarquons que si on inverse true  et false  dans le schéma de gauche on ne faitqu’affecter la négation de <condition> ( !<condition>) à maVariable.

if (<condition>) { <blocB> ; <blocA>

}else {

<blocC> ; <blocA>

if(<condition>) { <blocB>

}else { 

<blocC>}<blocA>

if (<cond1>) { if (<cond2>) { 

<blocA>} 

if (<cond1>&&<cond2>) { <blocA>

if (<cond1>) {

< blocA >}else { 

if (<cond2>) { <blocA>

if (<cond1>||<cond2>) { <blocA>

if (<condition>) {

maVariable=true ;}else { 

maVariable=false ;} 

maVariable=<condition>;

 

version davantage lisible

version davantage lisible 

version davantage lisible 

version davantage lisible

  Exercice PR008 p. 158  Corrigé p. 176 

Exercice PR009 p. 159  Corrigé p. 176 

Page 50: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 50/199

 

48 

Les  concepts de programmation  Programmation Visibilité/Accessibilité et encapsulation  [email protected] – B227 

3.12.  Visibilité/Accessibilité et encapsulation

Reprenons de la hauteur vis-à-vis de nos programmes en regardant davantage l’architecture (ledécoupage en classes et les liens elles) que les détails du code. Nous sommes passés rapidement sur la

notion de visibilité. Certes, nous avons justifié le fait que chacune de nos classes serait public par ledésir que toutes les parties de notre programme puissent y accéder. Mais nous avons ajouté que lesméthodes de nos classes seront presque tout le temps public  sans détailler les cas où elles seraient private. Nous n’avons pas non plus expliqué pourquoi les variables d’instances auront toujours private pour visibilité.

3.12.1.  Niveaux de visibilité

 Nous avons vu pour l’heure deux niveaux de visibilité. Nous en verrons un troisième lorsque nousaborderons le chapitre de l’héritage (cf. 3.27 page 90).

-   public : un membre (variable d’instance ou méthode) public est accessible partout.-   private : un membre déclaré private n’est accessible que par les méthodes de la classe où il est

déclaré.Et si on oublie de préciser la visibilité ? Il faut savoir que les applications réelles peuvent comporter

énormément de classes et pour ne pas s’y perdre on peut repartir ces classes en paquets. Il en va ainsid’ailleurs des classes fournies avec java ; elles sont regroupées thématiquement dans des paquets et on

 peut choisir d’utiliser tel ou tel paquet (nous y viendrons). Par défaut, si on ne précise ni public  ni private, le membre est accessible par toutes les classes de son paquet. C’est une sorte de public 

limité au paquet. Nous n’utiliserons pas le niveau de visibilité par défaut et nous préciserons donctoujours explicitement le niveau de nos membres.

Exemple

 public class A { private int x ;

 public int y ;

 private void  f() {this.x = 0 ; // acces autorisé

this.y = 0 ; // acces autorisé

this.g() ; // acces autorisé

}

 public void  g() {this.f() ; // acces autorisé

}}

 public class B { public void  h() {

A monA = new A();monA.x = 1 ; // Acces interdit car x est private dans A

monA.y = 1 ; // Acces autorisé car x est public dans A

monA.f() ; // Acces interdit car f() est private dans A

monA.g() ; // Acces autorisé car g() est public dans A

}}

Page 51: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 51/199

Les  concepts de programmation  Programmation Visibilité/Accessibilité et encapsulation  [email protected] – B227 

49 

3.12.2.  Des méthodes rarement private

Si la plupart des méthodes sont public  c’est parce qu’elles correspondent généralement à desservices permettant de manipuler l’objet qu’on souhaite mettre à disposition. Mais on peut vouloir ne paslaisser l’accès à un service. On parle alors de services internes, des méthodes qui ne servent qu’au sein de

la classe, généralement parce qu’il s’agit d’opérations de bas niveaux qui n’ont pas à être directementutilisées par les autres parties du programme.Prenons pour exemple des comptes bancaires. Chaque compte possède un solde mais nous devons

aussi pouvoir consulter un historique des opérations qui ont eu lieu sur le compte. Que peut-on faire surun compte ? Principalement déposer de l’argent, en retirer et consulter l’état du compte. Ces trois services

 peuvent utiliser des accesseurs pour manipuler l’état du compte mais on ne souhaite pas laisser l’accèsaux accesseurs en dehors de la classe. En effet, on ne veut fournir que les trois services identifiés. Si onautorise l’accès à setSolde  par exemple, on pourrait modifier le solde sans que l’opération soitmémorisée dans l’historique (on aimerait tous que notre banquier nous donne l’accès à setSolde ) etsi on autorise l’accès à l’historique, celui-ci pourrait être modifié sans que les opérations de dépôt etretrait relatives aient eu lieu.

Exemple public class CompteBancaire {

 private double solde ; private Historique h ;

 public CompteBancaire() {this.solde = 0.0 ;this.h = new Historiqe() ; 

} private void  setSolde(double s) {

this.solde = s ;}

 private double getSolde() {

return this.solde ;}

 private Historique getHistorique() {return this.h;

} public void  deposer( double montant ) {

this.setSolde( this.getSolde()+montant ) ;this.getHistorique().ajouter("depot de "+montant) ;

} public  boolean retirer( double montant ) {

if (this.getSolde()>=montant) {this.setSolde( this.getSolde()-montant) ;this.getHistorique().ajouter("retrait de "+montant) ;

return true ; // le retrait a pu avoir lieu}else {

return false ; // le retrait n’a pas pu avoir lieu

}}

 public void  afficher() {System.out.println("Le solde est de : "+this.getSolde()) ;System.out.println("Historique : "+this.getHistorique()) ;

}}

Un autre exemple est celui d’une classe modélisant un panneau d’affichage formé de diodes électrolu-

minescentes. Le seul service accessible de tous est l’affichage d’un message sur le panneau. Ce service pourrait toutefois s’appuyer sur une méthode interne ( private) allumant/éteignant une diode.

Page 52: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 52/199

 

50 

Les  concepts de programmation  Programmation Visibilité/Accessibilité et encapsulation  [email protected] – B227 

3.12.3.  L’encapsulation

Les variables d’instance permettent de représenter l’état d’un objet en mémoire. Mais toutes lescombinaisons de valeurs pour ces variables ne correspondent pas forcément à des états cohérents. Queserait un cercle de rayon négatif et à quel jour correspondrait la date du 32 février 2012 ? Le

 programmeur de la classe a connaissance des conditions garantissant une cohérence des données et ilveille à ce que le code de ses méthodes maintienne cette cohérence des données. Mais il est impossible degarantir cette cohérence si on laisse un accès public à nos données.

L’encapsulation vise à protéger les données des objets en ne permettant la manipulation des objetsqu’au travers de leurs méthodes. Bref, on ne permet pas d’accéder directement aux variablesd’instance. Nos variables d’instance seront toujours private. Les utilisateurs de la classe pourrontcréer des instances via les constructeurs, consulter/modifier l’état via les accesseurs ou encore appelern’importe quel service public de la classe, mais ils ne pourront pas accéder directement aux variablesd’instances et ne pourront donc pas rendre l’état incohérent.

D’ailleurs, l’utilisateur n’a pas à connaitre les variables d’instance. L’objet peut être vu comme uneboîte noire qu’on manipule sans en connaître les détails, ce qui n’est pas un problème pour peu qu’on

ait connaissance des spécifications des méthodes disponibles. C’est ce que vous avez fait avec la classeString. Vous ne savez pas comment sont représentées les String, mais vous connaissez via ladocumentation les méthodes accessibles et c’est suffisant pour les utiliser.

De la même manière, le détail du code est lui aussi superflu pour l’utilisateur de la classe. Seulesimportent les spécifications précises des méthodes. On fait abstraction de la représentation mémoire et dudétail du code. Les objets ne sont plus vus qu’au travers de leurs méthodes.

L’encapsulation accroît l’interchangeabilité. Oracle peut fournir une autre implémentation de la classeString  (jugée plus performante par exemple) sans que cela change le fonctionnement de vos

 programmes. Les programmeurs peuvent changer la représentation utilisée pour String  et peuventchanger le code des méthodes sans que cela ne perturbe les programmes utilisant cette classe pour peu

que les méthodes de leur nouvelle implémentation respectent les spécifications actuelles (les méthodesdoivent continuer de faire ce qui est précisé dans la documentation). Si au contraire les variablesd’instances de la classe String étaient publiques des utilisateurs à travers le monde auraient pu écriredes programmes qui accèdent directement à ces variables. Dès lors, les programmeurs de la classeString  seraient tenus de conserver cette représentation mémoire afin que les programmes utilisant laclasse String continuent de fonctionner.

Voir les classes comme des boites noires facilite également le développement en équipe. Supposonsque vous ayez un projet en équipe à réaliser. Plutôt que de travailler tous ensemble derrière le même écranvous souhaiteriez répartir le travail. Un moyen d’y parvenir est de songer d’abord tous ensemble à lamodélisation : quelles sont les types d’objets que va manipuler notre programme, et pour chacun de cestypes quels sont les services. Une fois cette analyse faite, chaque membre peut s’atteler à

l’implémentation d’une classe même si il n’a pas encore le code des autres. Connaissant les méthodesqu’auront les autres classes vous pouvez commencer à écrire du code les manipulant même si pourl’heure vous n’avez pas encore leurs implémentations.

Page 53: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 53/199

Les  concepts de programmation  Programmation Visibilité/Accessibilité et encapsulation  [email protected] – B227 

51 

3.12.4.  S’affranchir autant que possible de la représentation mémoire

 Nous venons de voir que le principe d’encapsulation permet aux classes utilisatrices d’une classe A des’affranchir de la représentation mémoire choisie pour A. Nous pouvons aller plus loin et adopter de

 bonne pratiques qui permettent de s’affranchir autant que possible de la représentation mémoire au sein

même d’une classe.Regardez les classes HeureBad et Heure ci-après. Toutes deux modélisent une heure via le nombre

de minutes écoulées depuis minuit. Les constructeurs et les accesseurs sont identiques. En revanche, lesautres services de HeureBad accèdent directement à la variable d’instance mnMinuit alors que ceuxde la classe Heure utilisent les accesseurs pour consulter l’état.

Supposons que nous décidions de changer de représentation mémoire en utilisant cette fois deux int,l’un pour les heures et l’autre pour les minutes. Quelles méthodes doivent être mises à jour ?

Le code des constructeurs doit être revu. Leur but étant d’initialiser les variables d’instance il estévident qu’un changement de représentation mémoire nous oblige à les mettre à jour. Les accesseursdoivent également être revus. Ils permettent d’accéder à l’état et si la représentation mémoire de l’étatchange il est normal que leur code évolue. Mais c’est tout ce qu’il y a à mettre à jour au niveau de la

classe Heure. Si les services de la classe HeureBad accèdent directement à l’état et doivent donc êtremodifiés, ceux de la classe Heure ne s’appuient pas sur les variables d’instance et demeurent corrects.

 public class HeureBad { private int mnMinuit;

//nombre de minutes ecoulees depuis minuit 

 public HeureBad(int mnMinuit){this.mnMinuit = mnMinuit;

} public HeureBad(int h, int mn) {

this.mnMinuit = (h*60 +mn);} public int getHeure() {

return this.mnMinuit /60;

} public int getMinutes() {

return this.mnMinuit %60;} public int getMnDepuisMinuit() {

return this.mnMinuit;} public  boolean equals(Object o){

return (o instanceof HeureBad)&& this.mnMinuit

==((HeureBad)o).mnMinuit;} public String toString() {

return(this.mnMinuit /60)+":"+(this.mnMinuit %60);

} public  boolean anterieure(

HeureBad heure) {return this.mnMinuit<heure.mnMinuit;

  }}

 public class Heure { private int mnMinuit;

// nombre de minutes ecoulees depuis minuit 

 public Heure( int mnMinuit) {this.mnMinuit = mnMinuit;

} public Heure(int h, int mn) {

this.mnMinuit = (h*60 +mn);} public int getHeure() {

return this.mnMinuit /60;

} public int getMinutes() {

return this.mnMinuit %60;} public int getMnDepuisMinuit() {

return this.mnMinuit;} public  boolean equals(Object o) {

return (o instanceof Heure)&& this.getMnDepuisMinuit()==((Heure)o).getMnDepuisMinuit();

} public String toString() {

return this.getHeure()+":"+this.getMinutes();

} public  boolean anterieure(Heure heure){

  return this.getMnDepuisMinuit()<heure.getMnDepuisMinuit();

}}

Exemple de classe (HeureBad) ayant des services accédant directement aux variables d’instance ; Tous les corps des méthodessont à revoir en cas de changement de représentation, ce qui n’est pas le cas si les services s’appuient sur les accesseurs (Heure).

 Nous adopterons donc la méthodologie ci-dessous lors de l’écriture d’une classe, afin notamment dene pas être contraint de revoir le code des services en cas de changement de représentation :

-  Déclaration (en private) des variables d’instance, représentant ainsi une vue de l’état de l’objet.-  Définition des constructeurs qui initialisent directement les variables d’instance.

-  Définition des accesseurs qui consultent/modifient directement les variables d’instance.-  Définition des autres services qui s’appuient sur les accesseurs et n’accèdent par conséquentqu’indirectement aux variables d’instance.

Page 54: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 54/199

 

52 

Les  concepts de programmation  Programmation Visibilité/Accessibilité et encapsulation  [email protected] – B227 

3.12.5.  javadoc

Comme vous avez pu le voir, la documentation des classes est essentielle. Pour utiliser une classe il estinutile de consulter son implémentation (son code). Il suffit de connaitre les spécifications des méthodesutilisables (accessibles/visibles) et donc sa documentation. Vous en avez déjà fait l’expérience avec la

classe String. La consultation de l’API Java vous a permis de connaître les services utiles à lamanipulation des chaînes de caractères.

Les documentations qui forment l’API java ont été générées avec un outil nommé javadoc. Cet outilsfourni avec le JDK exploite des commentaires spéciaux qui commencent par la séquence /**  et seterminent par */. Les autres commentaires (sur une ligne introduits par // ou sur plusieurs lignes initiés

 par /*  et terminés par */) ne sont pas utilisés pour la documentation car ils sont destinés à aider lacompréhension du code et non à éclairer sur la simple utilisation de la classe.

Au sein des commentaires javadoc des balises peuvent être exploitées, notamment @param  pourcommenter les paramètres d’une fonction et @return pour préciser ce qu’elle retourne. Eclipse facilitel’écriture de la documentation en rajoutant automatiquement les balises les plus utilisées (pour aller plus

loin, le site d’Oracle fournit une documentation de l’outil javadoc).En guise d’exemple, documentons la classe Point.

Sur la ligne avant la déclaration de la classe, tapez /** puis appuyez sur la touche entrée.

Eclipse complète en rajoutant la balise @author pour vous laisser la possibilité d’indiquer l’auteur.Au sein des commentaires javadoc, tapez @ : la complétion d’Eclipse vous propose les différentes

 balises utilisable à cet endroit.

Page 55: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 55/199

Les  concepts de programmation  Programmation Visibilité/Accessibilité et encapsulation  [email protected] – B227 

53 

Précisez les spécifications des méthodes. Pour cela, sur la ligne qui précède l’entête, tapez /**  puis appuyez sur la touche entrée. Indiquez ensuite via les balises @param  et @return  ce que laméthode prend pour paramètre et ce qu’elle retourne.

Une fois les commentaires javadoc rajoutés, vous pouvez lancer la génération de la documentationen allant dans le menu Project et en sélectionnant Generate javadoc.... Si comme ci-dessous la ligneJavadoc command  est vide, vous devez préciser à eclipse l’emplacement de l’outil javadoc. Pourcela, cliquez sur Configure puis recherchez  javadoc.exe  dans le sous-dossier bin du répertoire oùvous avez installé le jdk (généralement dans C:\Program Files\Java\jdk1.7.X_XX\bin\).

Après avoir cliqué sur Finish  javadoc génère un sous-dossier doc dans votre projet dans lequelvous trouverez des fichiers html  et notamment un fichier Point.html. Double-cliquez sur ce fichier

 pour l’ouvrir dans Eclipse et observer qu’il reprend la structure et la mise en forme de l’API java.

Page 56: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 56/199

 

54 

Les  concepts de programmation  Programmation Association, Agrégation et Délégation  [email protected] – B227 

3.13.  Association, Agrégation et Délégation

3.13.1.  Agrégation et délégation

Continuons de regarder nos programmes avec de la hauteur pour voir les liens possibles entre les

classes. Prenons l’exemple de la classe Cercle. Nous l’avons modélisée par la donnée d’un Point (lecentre) et d’un double  (le rayon). On peut dire qu’un Cercle  est composé d’un Point et d’unrayon, ou encore qu’un Cercle  a un centre (de type Point) et un rayon. Cette relation qui lie uneclasse composite (Cercle) à l’une de ses parties (ici Point) et dit d’ agrégation. La classe Cercle agrège, dans le sens « réunir pour former un ensemble » du terme, une instance de Point et undouble. Nous avons donc déjà fait de l’agrégation sans le savoir.

L’agrégation se traduit dans l’état de la classe composite par la présence d’une référence du type de laclasse agrégée. Et si on a une référence vers un objet, on peut appeler une méthode sur cet objet. Doncd’un point de vue comportement, la référence correspondant à l’agrégation va permettre de solliciter la

 partie pour par exemple lui  déléguer une tâche. Sur notre exemple, nous pourrions vouloir ajouter uneméthode à la classe Cercle  permettant de le déplacer. La position du cercle n’est pas mémorisé

directement dans Cercle, c’est via son instance de Point  que la position du cercle est mémorisée.Pour modifier la position d’un Cercle on doit donc déléguer la requête à son centre. C’est ce qui est faitdans l’extrait de code ci-dessous où la méthode deplacer  de Cercle  fait appel à la méthodedeplacer de Point.

Exemple

 public class Cercle { private Point centre ; private double rayon ;

… public Point getCentre() {

return this.centre;} public void  deplacer(double dx, double dy ) {

this.getCentre().deplacer(dx, dy);}

}

3.13.2.  Association

Prenons un autre exemple, celui d’une agglomération qui souhaite réaliser une simulation de lacirculation qu’il y a dans ses rues afin de voir si des aménagements pourraient améliorer la fluidité dutrafic. Pour cette simulation, chaque véhicule pourrait être modélisé par un point de départ, un horaire de

départ, un point d’arrivée, une position actuelle, voire éventuellement d’autres caractéristiques. Onretrouve là un lien d’agrégation : la classe Vehicule agrège une instance d’Horaire à trois instancede Position et à éventuellement d’autres instances. Un véhicule a un horaire de départ, a une positionde départ, …. Le réseau urbain pourrait lui être modélisé par un ensemble de voies, lesquelles relient desintersections, et bien sûr par l’ensemble des véhicules. Là encore, on retrouve de l’agrégation, et le réseauurbain ayant des références vers ses voies et ses véhicules, il sera en mesure d’appeler des méthodes surses constituants.

Comment faire la simulation ? On aimerait voir les véhicules évoluer à travers la ville. Le réseauurbain pourrait à intervalle de temps régulier, disons par exemple toutes les secondes, demander à chacunde ses véhicules d’effectuer le déplacement correspondant à une seconde de trajet. Vu que le réseauurbain à une référence vers ses véhicules il peut le faire. Il suffit que la classe Vehicule possède uneméthode deplacer(int duree)  qui met à jour sa position actuelle pour simuler un déplacementd’une durée de duree secondes. La classe composite peut faire appel à des méthodes sur les instancesqu’elle agrège parce qu’elle a une référence vers ces instances. Mais une référence est à sens unique. Le

Page 57: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 57/199

Les  concepts de programmation  Programmation Association, Agrégation et Délégation  [email protected] – B227 

55 

véhicule n’a lui aucun lien vers son réseau urbain. Pourtant un lien serait ici utile puisque la méthodedeplacer(int duree) devrait pouvoir demander au réseau urbain quelles sont les voies accessiblesà la prochaine intersection, ou demander si il y a un autre véhicule entravant son déplacement(habituellement, un conducteur essaye d’éviter les collisions). Que faire pour que les véhicules puissentaccéder aux méthodes de leur réseau urbain ? Utiliser une référence bien sûr. Chaque véhicule doit avoir

une variable d’instance référençant son réseau urbain. Mais l’ajout de cette référence ne constitue pas uneagrégation. Un réseau urbain n’est pas une partie d’un véhicule. On ne peut pas dire que chaque véhiculea son réseau urbain, mais qu’il connaît son réseau urbain. C’est un lien d’ association.

L’agrégation n’est qu’un cas particulier d’association. L’association n’est qu’un lien structurel entredeux classes. Il se peut fort bien que les deux classes soit au même niveau conceptuel, aucun n’étant plusimportant que l’autre et on parle alors d’association simple. C’est ce qui correspond à la relation« connait ». Mais il se peut aussi que le lien soit entre une classe composite (le « tout ») et une classeagrégée (la « partie ») et on parle alors d’agrégation. La relation correspond alors au verbe avoir ouagréger. Il existe d’autres liens possibles entre les classes comme la composition qui est un cas particulierd’agrégation dans laquelle la partie ne se conçoit pas sans son tout et où une partie ne peut figurer quedans un seul objet composite, ou encore la dépendance notamment lorsque des méthodes d’une classe A

 prennent en paramètre des objets d’une classe B, mais nous nous limiterons pour l’heure à l’associationsimple et à l’agrégation.

3.13.3.  Pseudo diagramme de classe

Un schéma vaut souvent mieux qu’un long discours. Un diagramme de classe permet de synthétiserl’ensemble des informations d’une modélisation en donnant un aperçu des classes (avec leurs états etleurs comportements) et des relations qu’il y a entre elles.

Dans un diagramme de classe, chaque classe est représentée par un rectangle et les liens entre ellessont symbolisés par des arcs dont les extrémités diffèrent. Le rectangle d’une classe est subdivisé en trois

 parties contenant respectivement le nom de la classe, les variables d’instance et les entêtes des méthodes.

Une forme particulière est habituellement utilisée pour préciser les variables d’instances et les méthodes,mais comme le sous-entend le titre de cette section nous n’utiliserons qu’une forme simplifiée desdiagrammes de classe. Nous utiliserons la syntaxe java des déclarations avec pour seul changementl’indication de la visibilité par un unique caractère : - pour private et + pour public.

Une association directionnelle sera symbolisée par une flèche , une association bidirectionnelle parun trait , et une agrégation par un trait accompagné d’un losange du coté de la classe agrégeante .

Ainsi, la modélisation retenue pour Cercle pourrait être schématisée par le diagramme suivant :

Cercle

- Point centre- double rayon

+ Cercle(Point pt, double r)+ Point getCentre()+ double getRayon()+ double getPerimetre()+ double getAire()+ void deplacer(double dx,

double dy)+ boolean equals(Object o)+ String toString()

Point

- double abscisse- double ordonnee

+ Point()+ Point(double x, double y)+ int getAbscisse()+ int getOrdonnee()+ void setAbscisse(double x)+ void setOrdonnee(double y)+ void deplacer(double dx,

double dy)+ boolean equals(Object o)+ double distance(Point pt)+ String toString()

Page 58: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 58/199

 

56 

Les  concepts de programmation  Programmation Association, Agrégation et Délégation  [email protected] – B227 

Résumé-   Nous préciserons toujours explicitement la visibilité et n’utiliserons jamais la visibilité par défaut.-   Nous adopterons la méthodologie ci-dessous lors de l’écriture d’une classe :

o  Déclaration en private des variables d’instance, représentant une vue de l’état de l’objet

o  Définition des constructeurs qui initialisent directement les variables d’instance.o  Définition des accesseurs qui consultent/modifient directement les variables d’instance.o  Définition des autres services qui s’appuient sur les accesseurs et n’accèdent par

conséquent qu’indirectement aux variables d’instance.-  Avec le principe d’encapsulation un objet peut-être vu comme une boîte noire qu’on manipule

sans en connaître les détails. Les informations utiles à l’utilisateur d’une classe se résument à la javadoc de la classe.

-  Javadoc est un outil permettant de générer automatiquement une documentation du code à partirdes commentaires spécifiques mentionnés par le programmeur.

-  L’association simple  est un lien structurel (en ce qui nous concerne, une référence vers) d’uneclasse A vers une classe B, les deux classes étant de même niveau conceptuel. Ce lien correspondau verbe connaître. A connaît B, dans le sens où A possède une référence de type B et peut donc

faire appel à des méthodes sur cette référence. Ce lien est symbolisé dans un diagramme de classe par une flèche .

-  L’agrégation est une association entre une classe composite (le « tout ») et une classe agrégée (la  « partie »). Ce lien correspond au verbe avoir. A a un B dans le sens où l’une de ses parties estune instance de B. A possédant une référence de type B elle peut bien sûr invoquer des méthodessur sa partie, notamment pour déléguer une tâche. Ce lien est symbolisé dans un diagramme declasse par un trait accompagné d’un losange du coté de la classe agrégeante .

Page 59: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 59/199

Les  concepts de programmation  Programmation Retour  sur les constructeurs  [email protected] – B227 

57 

3.14.  Retour sur les constructeurs

3.14.1.  Recopie profonde / superficielle

Une classe peut bien sûr avoir plusieurs constructeurs. Rappelons que l’état correspond à UNE vue du

concept et on ne mémorise pas toujours toutes les caractéristiques car certaines peuvent être redondantes.Pour le rectangle par exemple, le fait de le représenter en mémoire par deux de ses sommets opposéssuffit, il est inutile de mémoriser en plus la largeur et la hauteur par exemple car on peut les déduire descoordonnées des sommets. Mais ce n’est pas parce qu’on ne mémorise qu’indirectement la largeur qu’onne doit pas avoir le getter getLargeur(). Les méthodes et en particulier les accesseurs et lesconstructeurs de doivent pas dépendre du choix réalisé pour la représentation mémoire. Pour un nombrecomplexe, l’utilisateur doit pouvoir le manipuler aussi bien via un point de vue cartésien que via unevision polaire.

Regardons quelques constructeurs que nous pourrions envisager pour la classe Cercle. Quel codeécririez-vous pour Cercle(double xCentre, double yCentre, double rayon) ? Il y a

 peu de possibilités. Le but du constructeur est d’initialiser les variables d’instances et donc ici d’initialiser

this.rayon  avec rayon  et this.centre  avec un nouveau  Point qui aura (xCentre,yCentre) pour coordonnées.

Exemple

 public class Cercle { private Point centre ; private double rayon ;

 public Cercle(double xCentre, double yCentre, double rayon) {this.centre = new Point(xCentre, yCentre) ;this.rayon = rayon ;

}…

}

Quel code écririez-vous pour Cercle(Cercle c)  ? On a envie d’initialiser l’état à partir desdonnées d’un cercle existant. Là, il y a un véritable choix à faire. Pour this.rayon, pas d’hésitation.Il s’agit d’une variable de type primitif et tout ce qu’on peut faire c’est l’initialiser avec la même valeurque le rayon de c. Par contre pour this.centre on peut soit faire en sorte qu’elle désigne le même

 point que le centre de c (les deux cercles partageraient la même instance de Point pour centre, on parlede copie superficielle) soit la faire référencer un nouveau point, initialement confondu avec le centre de c (chaque cercle aurait sa propre instance de Point pour centre, on parle de copie profonde). Il n’y a pasde bonne et de mauvaise solution ici. On doit choisir en fonction du contexte d’utilisation.

Avec la copie superficielle les deux instances de cercles sont dépendantes puisqu’elles partagent lemême centre. Si on change les coordonnées du centre de l’un des cercles, l’autre cercle est lui aussidéplacé. Cela peut correspondre à un souhait. Par exemple, si le contexte est la réalisation d’un logiciel deconception assistée par ordinateur, on peut vouloir faire en sorte que le centre de la roue d’un vélo quel’on dessine soit toujours confondu avec le centre des pignons (et l’emplacement choisi sur le cadre pourl’axe de la roue). Ainsi, si on déplace la roue, les pignons seront eux aussi déplacés, et vice versa.

Avec la copie profonde, les deux cercles sont indépendants. Certes, ils seront confondus initialement,mais chacun à son propre exemplaire de Point pour mémoriser son centre. On peut déplacer le centred’un des cercles sans que cela n’affecte l’autre cercle.

Si les deux scénarios sont potentiellement souhaitables, il est statistiquement bien plus rare d’opter pour la copie superficielle car on a plus rarement besoin de telles dépendances entre les objets créés. Dans

le cadre de ce cours, le comportement par défaut (sauf mention contraire) attendu sera la copie profonde.

Page 60: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 60/199

 

58 

Les  concepts de programmation  Programmation Retour sur les constructeurs  [email protected] – B227 

Exemple

// Version copie superficielle public class Cercle {

 private Point centre ; private double rayon ;

 public Cercle(Cercle c) {this.centre = c.getCentre();this.rayon = c.getRayon();

} public Point getCentre() {

return this.centre;} public Point getRayon() {

return this.rayon;}

…}

// Version copie profonde public class Cercle {

 private Point centre ; private double rayon ;

 public Cercle(Cercle c) {this.centre = new Point(

c.getCentre().getAbscisse(),  c.getCentre().getOrdonnee());  this.rayon = c.getRayon();

} public Point getCentre() {

return this.centre;}

 public Point getRayon() {return this.rayon;

}…

}

Les schémas mémoire ci-dessous illustrent les situations après la troisième ligne de la méthode main de Test selon que l’on ait opté pour une copie superficielle ou pour une copie profonde. Avec la copiesuperficielle le changement d’abscisse du centre de c1 modifie l’abscisse du centre de c2 puisque les deuxcercles partagent tous deux le même centre. A l’inverse, avec la copie profonde, chaque cercle a sa propreinstance de Point pour centre et le centre de c2 n’est pas affecté par les modifications du centre de c1. public class Test {

 public static void  main(String[] arg) {Cercle c1 = new Cercle(2.0, 3.0, 1.0);Cercle c2 = new Cercle(c1);c1.getCentre().setAbscisse( 4.0 ) ;

…}}

abscisse

ordonnee

4.0

3.0

centre

rayon 1.0

c1 centre

rayon 1.0

c1 abscisse

ordonnee

4.0

3.0

centre

rayon 1.0

c2 centre

rayon 1.0

c2 abscisse

ordonnee

2.0

3.0

Page 61: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 61/199

Les  concepts de programmation  Programmation Retour  sur les constructeurs  [email protected] – B227 

59 

3.14.2.  Chaînage de constructeurs

 Nous pourrions vouloir ajouter d’autres constructeurs. Par exemple un constructeur sans paramètre quiinitialiserait le cercle avec l’origine du repère pour centre et un rayon arbitrairement de 1.0. ou encore unconstructeur prenant deux points en paramètres et initialisant l’instance de sorte que le segment qui a les

arguments pour extrémités soit un diamètre du cercle. Tous ces constructeurs peuvent se ramener au premier que nous avons écrit. Plutôt que de réécrire du code similaire, on aimerait bien sûr pouvoirappeler ce constructeur. Un constructeur peut en appeler un autre, on fait alors du chaînage deconstructeurs. Syntaxiquement, l’appel d’un autre constructeur est noté this( args )  où args

sont les arguments fournis. Ne pas confondre this (dans les méthodes d’instance, la référence sur

l’objet receveur) et this( …) qui marque l’appel d’un autre constructeur de la même classe.

Bien sûr, il faut au moins un constructeur qui réalise les initialisations sans faire appel à un autreconstructeur. Les constructeurs ne doivent pas se rejeter la tâche les uns les autres.

L’intérêt du chaînage est d’autant plus important si de nombreuses opérations sont effectuées dans leconstructeur (ce qui n’est pas vraiment le cas dans l’exemple donné ci-dessous). Mais au-delà de l’aspect« factorisation du code », le chaînage de constructeur a également l’intérêt de limiter les mises à jour à

effectuer en cas de changement de représentation mémoire. Si par exemple nous décidons de ne plusmémoriser le rayon mais le diamètre, seul le premier constructeur serait à modifier, les autresdemeureraient valides.

Enfin, notez qu’un appel à this( …)  ne peut avoir lieu que sur la première ligne d’un

constructeur. Vous ne pouvez donc pas effectuer des tâches puis appeler un autre constructeur. Vousdevez appeler le constructeur en premier.

Exemple

 public class Cercle { private Point centre ; private double rayon ;

 public Cercle(double xCentre, double yCentre, double rayon) {this.centre = new Point(xCentre, yCentre) ;this.rayon = rayon ;

} public Cercle(Cercle c) {

this(c.getCentre().getAbscisse(),c.getCentre().getOrdonnee(),rayon) ;}

 public Cercle() {this(0.0, 0.0, 1.0) ;

} public Cercle(Point p1, Point p2) {

this((p1.getAbscisse()+p2.getAbscisse())/2.0 ,(p1.getOrdonnee()+p2.getOrdonnee())/2.0 ,

p1.distance(p2)/2.0) ;}…

}

Résumé-  Un constructeur effectue une  copie superficielle  si l’objet initialisé pourra potentiellement

 partager des données avec un autre.-  Un constructeur effectue une  copie profonde  si l’objet initialisé aura sa propre copie de

l’information, indépendante de tout autre objet.-  Un constructeur peut appeler un autre constructeur de la même classe en précisant this(args) 

sur sa première ligne (où args sont les arguments du constructeur appelé).

-   Ne pas confondre  this  (dans les méthodes d’instance, la référence sur l’objet receveur) et this(…) qui marque l’appel d’un autre constructeur de la même classe.

Page 62: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 62/199

 

60 

Les  concepts de programmation  Programmation Les tableaux  [email protected] – B227 

3.15.  Les tableaux

Dans le chapitre précédent nous avons évoqué l’exemple d’un réseau routier qui possède dans son étatun ensemble de véhicule. Si chaque réseau routier n’avait que trois véhicules, on pourrait déclarer troisvariables d’instances, v1, v2  et v3  de type Vehicule. Mais c’est peu réaliste. On pourrait déclarerautant de variables d’instances qu’il y a de véhicules, mais d’une part ce nombre n’est pas le même d’unréseau routier à un autre, et d’autre part le code serait particulièrement lourd. Il nous faut un moyen demémoriser un nombre variable d’informations, et c’est ce qu’offrent les tableaux.

Les tableaux (également appelés vecteurs lorsqu’ils sont à une dimension et  matrices lorsqu’ils sontde dimension 2) sont des suites homogènes (c’est-à-dire ayant toutes le même type) de variables,accessibles par un index (les cases mémoire utilisées étant consécutives).

Les tableaux sont donc des types composites, au même titre que les classes, et une variable de typetableau est donc une référence. Une référence qui va désigner une plage continue de variables de mêmetype, contrairement aux références sur des objets qui eux peuvent agréger des données hétérogènes.

Avant de nous attaquer à des exemples plus réalistes, observons l’utilisation d’un tableau dans le bout

de programme suivant.… boolean conjonction; // le "ET" entre les booleens du tableau 

// déclaration du tableau monTableau

 boolean[] monTableau;

// allocation mémoire de 3 booléens pour monTableau

monTableau = new  boolean[ 3 ];

// initialisation de monTableau

monTableau[ 0 ] = true;monTableau[ 1 ] = false;monTableau[ 2 ] = true;

// utilisation de monTableau

conjonction = ((monTableau[0] && monTableau[1]) && monTableau[2]);System.out.println("la conjonction des "+monTableau.length

+" Booleens est "+conjonction);

// on n’a plus besoin du tableau : on affecte la référence à null

monTableau = null; …

L’algorithme est commenté, ce qui facilite sa lecture. Nous voyons que la déclaration d’un tableaun’est pas différente de celle des autres variables. On découvre juste un nouveau type de données, ou plutôtun constructeur de types : si T est un type, alors T[] correspond à un tableau dont les éléments sont de

type T. Ici, on déclare un tableau qui va contenir des Booléens, mais nous serons amenés plus loin dans cecours à déclarer des tableaux d’entiers, des tableaux d’objets, et même des tableaux de tableaux.

L’état de la mémoire après la déclaration de monTableau est le suivant :

monTableau est une référence qui va contenir l’adresse de la plage continue de Booléens. Mais pourl’heure monTableau n’a pas été initialisée et ne désigne rien du tout.

monTableau est initialisée à la ligne suivante via l’opérateur new. Nous avons déjà vu l’emploi del’opérateur  new  pour la création d’objets mais ici il s’agit de la création d’un tableau et la syntaxediffère. Au lieu d’indiquer entre parenthèses les paramètres d’un constructeur on précise entre crochets la

taille que doit avoir le tableau. On indique ici « affecte à monTableau l’adresse d’un nouveau tableaude 3 Booléens ». new va d’abord rechercher dans la mémoire une plage libre suffisamment longue pour

conjonction monTableau??? ???

Page 63: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 63/199

Les  concepts de programmation  Programmation Les tableaux  [email protected] – B227 

61 

contenir 3 Booléens. Il va ensuite mémoriser que cette plage est à présent allouée puis il retourneral’adresse de cette plage qui sera affectée à monTableau. L’état de la mémoire devient donc :

Le bout de programme affecte ensuite les cases/éléments de monTableau. monTableau[i] désigne le (i+1)ème  Booléen de monTableau. En effet, monTableau[i]  est l’élément auquel onaccède en se décalant de i éléments (ici des Booléens) à partir de l’élément désigné par monTableau.monTableau[0]  est donc le premier élément de monTableau, monTableau[1]  est quant à luicelui auquel on accède en se décalant d’un Booléen à partir du début du tableau. monTableau[1] estdonc le deuxième Booléen. Enfin, en se décalant de 2 Booléens à partir du début on accède àmonTableau[2] qui n’est autre que le 3ème Booléen du tableau.

Remarque

Attention au décalage entre index et rang. Si t  est un tableau, l’élément d’index i  (t[i]) est le(i+1)ème élément (et a donc i+1 pour rang). 

Les trois affectations conduisent donc à l’état suivant de la mémoire :

monTableau[i] désigne une case mémoire pouvant contenir un Booléen. Il s’agit donc d’unevariable Booléenne qu’on peut affecter (comme nous venons de le faire) mais aussi consulter.L’affectation de conjonction en est une illustration puisqu’on consulte la valeur des trois Booléens demonTableau pour en déterminer la conjonction (le « et logique »).

L’exemple montre également que chaque tableau possède après son allocation un champ mentionnant

sa taille. Si on a alloué n  cases pour un tableau t, alors t.length  vaut n. Ainsi le bout de codeaffichera "La conjonction des 3 Booleens est false". Notez qu’on ne peut pas affecter le champ length  d’un tableau. On peut le consulter pour connaitre la taille, mais ce n’est clairement pas unmoyen pour modifier la taille d’un tableau. On ne peut pas modifier la taille d’un tableau. On ne peut

 pas rajouter ou retirer des cases à un tableau. On peut par contre réaffecter une référence pour qu’elledésigne un nouveau tableau, plus petit ou plus grand. Ainsi, sur notre exemple, si on voudrait que t désigne à présent un tableau de 4 Booléens il faudrait créer (via new) un nouveau tableau de 4 Booléens,éventuellement recopier les valeurs des cases de t dans ce nouveau tableau puis affecter t avec l’adressede ce nouveau tableau.

Enfin, la mémoire d’un ordinateur n’est pas infinie et il convient de libérer l’espace mémoire dont onne se sert plus afin d’en faire profiter les autres programmes en cours d’exécution. En affectant la valeurnull  à la référence monTableau  on permet au  ramasse-miettes  de libérer la plage de 3 Booléens

 puisque plus aucune référence ne permet d’y accéder. Nous aurions pu attendre d’atteindre la fin de la portée de la variable monTableau. La référence monTableau  n’existerait alors plus et l’espacequ’elle désignait serait libéré par le ramasse-miettes. On choisit ici de ne pas attendre en affectant uneautre valeur à monTableau (null en l’occurrence).

Tout comme pour les objets, la durée de vie d’un tableau en mémoire n’est donc pas limitée à une portée, mais est assujettie au fait d’être désigné par une référence.

Important !

Etant donné un tableau t, on ne peut consulter t[i]  avec i [0, …, t.length-1] ou

t.length QU’APRES avoir réservé l’espace mémoire nécessaire via l’opérateur new.

conjonction monTableau??? ??? ??? ???

conjonction monTableau??? true false true

conjonction monTableaufalse true false true

Exercice PR010 p. 160  Corrigé p. 176 

Page 64: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 64/199

 

62 

Les  concepts de programmation  Programmation Les tableaux  [email protected] – B227 

La principale source d’erreurs concerne les index lors de l’accès à un élément.

Important !

Etant donné un tableau t, seuls t[0], t[1], …, t[ t.length-1 ] ont du sens. Accéder à

t[i] avec i[0, …, t.length-1] provoque une erreur.

Java propose une alternative pour initialiser les tableaux via une énumération de ses valeurs entreaccolades.

Exempleint[] t = { 2, 3, 5, 7};// équivalent à :

// int[] t = new int[4];

// t[0] = 2;

// t[1] = 3;

// t[2] = 5;

// t[3] = 7;

String[] couleursFr = {"Bleu", "Blanc", "Rouge"};

// équivalent à :// String[] couleursFr = new String[3];

// couleursFr[0] = "Bleu";

// couleursFr[1] = "Blanc";

// couleursFr[2] = "Rouge";

On ne peut toutefois utiliser ces constantes de type tableau que lors d’une initialisation conjointe à unedéclaration. Il est notamment impossible d’écrire int[] t;  puis  t={2, 3, 5, 7}; 

Un tableau de dimension 2 (une matrice) n’est rien d’autre qu’un vecteur de vecteurs. Nous pouvonsdonc déclarer et utiliser des tableaux multidimensionnels comme dans l’exemple ci-dessous manipulantune matrice triangulaire.

Exemple

 public class TestMatrices { public static void main(String[] args) { 

int[][] m = {{1,2,3}, {4, 5}, {6}};// équivalent à

// int[][] m = new int[3][];// m[0] = new int[3];// m[1] = new int[2];// m[2] = new int[1];

// m[0][0]=1;

// m[0][1]=2;

// m[0][2]=3;

// m[1][0]=4;

// m[1][1]=5;

// m[2][0]=6;

 boolean[][] m2 = new boolean[2][3];System.out.println("La matrice m est un vecteur de "+m.length+" vecteurs, le premier etant de longueur "+m[0].length+" et le dernier de longueur "+m[2].length);

System.out.println("m2 est une matrice rectangulaire de "+m2.length+"x"+m2[0].length+" booleens.");

}}

Affichage produit :La matrice m est un vecteur de 3 vecteurs, le premier etant de

longueur 3 et le dernier de longueur 1m2 est une matrice rectangulaire de 2x3 booleens.

Page 65: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 65/199

Les  concepts de programmation  Programmation Les tableaux  [email protected] – B227 

63 

 Notez que là encore il est possible d’utiliser des constantes de type matrice (ici {{1,2,3}, {4,5}, {6}}) uniquement lors d’une initialisation conjointe à la déclaration. De plus, lorsque la matriceest rectangulaire il est possible de réserver l’intégralité de l’espace nécessaire en une seule instruction en

 précisant les dimensions sur les diverses dimensions (ici new boolean[6][12]).

Combien de lignes comporte la matrice ? Tout dépend au sens que VOUS accordez aux différentesdimensions. Dans la mémoire il n’y a pas de notion de verticalité/horizontalité. On peut juste dire quedans le cas d’une matrice rectangulaire m  le premier index va de 0  à m.length-1  et que le secondindex va de 0 à m[0].length-13. Les deux schémas ci-dessous sont acceptables comme illustration del’occupation mémoire de m2 car tout dépend si on voit m2 comme une matrice de 2 lignes ou comme unematrice de 2 colonnes. L’important est de rester cohérent tout au long du programme et de se tenir auchoix qu’on a fait quant à la sémantique des différentes dimensions.

A présent que nous avons introduit les tableaux nous pouvons lever le voile sur le paramètre de laméthode main. Lorsqu’on lance l’exécution d’un programme on peut préciser des paramètres. Souseclipse, lorsqu’on fait un clic-droit sur le nom de la classe contenant la méthode main  et qu’onsélectionne Run As, il faut choisir Run Configurations plutôt que Java Application puis préciser dansl’onglet Arguments les paramètres. Mais on peut aussi lancer un programme java sans eclipse. Dans uninterpréteur de commandes (terminal / Shell) il faut se placer dans le répertoire contenant le bytecode ettaper « java NomClasse » où NomClasse est la classe contenant la méthode principale. On peut passer

des paramètres après le nom de la classe et taper par exemple « java NonClasse Fer 20.5 Nickel 4.3».Le tableau qui fait office de paramètre dans la méthode main  contient alors ces différents paramètressous la forme de chaînes de caractères. Sur notre exemple, le tableau comporterait alors quatre casescorrespondantes aux chaînes « Fer », « 20.5 », « Nickel » et « 4.3 ».

Résumé-  si T est un type, alors T[] correspond à un tableau dont les éléments sont de type T.-  Les  tableaux  sont des suites homogènes (c’est-à-dire ayant toutes le même type) de variables,

accessibles par un index (les cases mémoire utilisées étant consécutives).-  Les tableaux étant des types composites, une variable de type tableau est une référence.-  new T[ x ] alloue un tableau de x variables de type T.

-  Si t est un tableau alors t.length désigne sa taille.-  On ne peut pas modifier la taille d’un tableau et on ne peut pas affecter une valeur à t.length.-  Etant donné un tableau t, on ne peut consulter t[i]  avec i[0, …, t.length-1] ou

t.length QU’APRES avoir réservé l’espace mémoire nécessaire via l’opérateur new.-  Etant donné un tableau t, seuls t[0], t[1], …, t[ t.length-1 ] ont du sens. Accéder à

t[i] avec i[0, …, t.length-1]  provoque une erreur.-  Une matrice est un tableau de tableaux. new T[x][y] crée une matrice rectangle de taille xxy.-  Java possède une syntaxe permettant l’initialisation d’un tableau lors de sa déclaration.-  Ex. : int[] t = { 2, 3, 5, 7}; où int[][] m = {{1,2,3}, {4, 5}, {6}}; 

3 Si m est de type int[][], alors m[i] est de type int[]. On retrouve bien là qu’une matrice est un tableau de tableaux. m[i] étant untableau, sa taille est accessible via le champs length (m[i].length).

m2 m2

m2[0]

m2[1](type int[])

m2[0][1](type int)

m2.length

m2  [ 1  ]  .l  en  g th 

m2 (type

int[][])

Aparté

Page 66: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 66/199

 

64 

Les  concepts de programmation  Programmation Les boucles while  [email protected] – B227 

3.16.  Les boucles while 

Via les tableaux nous avons à présent un moyen de représenter des ensembles de données de mêmetype. Nous pourrions par exemple écrire une classe SetOfBool  représentant des ensembles deBooléens, chaque instance pouvant avoir un nombre d’éléments différent.

Exemple public class SetOfBool { 

 private boolean[] lesBooleens;/*** initialise l’instance de sorte qu’elle corresponde à un ensemble vide* Attention : ci-dessous on initialise la référence avec un tableau de* taille 0, ce qui est différent d’initialiser à null.*/ public SetOfBool() {

this.lesBooleens = new boolean[0]; }…

Mais nos connaissances du langage java sont encore limitées et nous aurons des difficultés à écriretoutes les méthodes pour une telle classe. Focalisons nous sur la méthode conjonction  censéeretourner le « et logique » entre les éléments de l’ensemble. Nous pourrions écrire le début de code ci-dessous.

Exemple erroné !!! …/*** @return si l’ensemble est vide, retourne true, sinon, retourne* la conjonction des booléens de l’ensemble

*/ public boolean conjonction( ) {

 boolean c = true;if (this.lesBooleens.length>0) {

c = c && this.lesBooleens[0];}if (this.lesBooleens.length>1) {

c = c && this.lesBooleens[1];}if (this.lesBooleens.length>2) {

c = c && this.lesBooleens[2];}

return c;}

Le code ci-dessus ne fonctionne que si l’ensemble comporte au plus 3 Booléens. Si on pense l’utiliseravec des ensembles contenant 4 Booléens on pourrait rajouter une conditionnelle. On voit de toute façonqu’on réalise le même traitement pour chacun des Booléens de l’ensemble. Mais si les ensemblescomportent 5, 10, 100 ou 1000 Booléens ? On ne peut pas raisonnablement traiter individuellementchacun de cas, le code deviendrait particulièrement lourd et les risques d’erreurs seraient grands. Et àquelle borne devrions nous nous arrêter ? Qui nous dit que les ensembles ne pourraient pas être plusgrands encore ? Il nous faudrait un moyen de généraliser notre code en répétant l’action pour tous lesBooléens de l’ensemble.

Les  boucles  permettant de répéter une action. Nous voudrions ici exprimer le fait qu’après avoirinitialisé c à true, l’affectation c = c && this.lesBooleens[i]doit être effectuée tant qu’elle

Page 67: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 67/199

Les  concepts de programmation  Programmation Les boucles while  [email protected] – B227 

65 

n’a pas été faite pour tout i  de 0  à this.lesBooleens.length-1. Nous obtiendrions ainsi laconjonction des Booléens de lesBooleens. Ce « tant que… » va être traduit par une structurerépétitive ( boucles) dont la syntaxe est la suivante.

while (<condition>) {

<corpsDeLaBoucle> }

La boucle while  (<condition>){<corpsDeLaBoucle>} permet de réaliser un blocd’instructions (le corps de la boucle, délimité comme tout bloc d’instruction par des accolades) tantqu’une condition est vérifiée. Si condition  est vérifiée, corpsDeLaBoucle  sera exécuté, puiscondition  sera à nouveau évaluée et si elle est encore vraie corpsDeLaBoucle  sera exécuté, etainsi de suite tant que condition est vraie (vaut true).

Condition est bien évidemment une expression à valeur Booléenne puisque son évaluation doitconduire à true ou false.

Voici une première solution (améliorable) pour notre fonction etDeBooleens.

Exemple améliorable !!!  public boolean conjonction( ) {

 boolean c = true;int index = 0;while (index < this.lesBooleens.length) {

c = c && this.lesBooleens[ index ];index = index + 1;

}return c;

}

Détaillons les instructions exécutées durant l’exécution de la procédure principale ci-dessous ensupposant que l’accesseur add( boolean b)  rajoute un Booléen de valeur b  dans l’ensemble (nousverrons plus tard comment).

 public static void main(String[] args) {SetOfBool set = new SetOfBool( );set.add(true);set.add(false);set.add(true);System.out.println( set.conjonction( ) );…

}

L’état de la mémoire après l’exécution de la première ligne est le suivant :

A l’issue des trois appels à la méthode add, l’état de la mémoire peut-être schématisé par :

L’appel à conjonction  conduit à l’allocation mémoire de this  qui va être initialisée avecl’adresse de l’objet receveur, donc la valeur de set. De plus la première ligne de conjonction déclareet initialise à true la variable locale c et la seconde déclare et initialise la variable locale index à 0.Après les deux premières lignes de conjonction l’état de la mémoire est donc :

set lesBooleens

set lesBooleens truefalsetrue

Page 68: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 68/199

 

66 

Les  concepts de programmation  Programmation Les boucles while  [email protected] – B227 

La valeur de la condition (index<this.lesBooleens.length)est true puisque la longueurdu tableau est 3. Le corps de la boucle est par conséquent exécuté une première fois conduisant à l’état dela mémoire suivant :

La condition est à nouveau évaluée et sa valeur étant true  le corps de la boucle est exécuté ànouveau. La conjonction avec le 2ème Booléen du tableau rend c false. L’état de la mémoire devient :

La condition étant encore vérifiée, le corps est exécuté une troisième fois conduisant à l’état :

La condition est à présent fausse, la boucle est terminée et on passe donc à l’instruction suivante. Lavaleur de c est retournée, c’est donc cette valeur qui sera affichée.

Le déroulement peut-être illustré par la flèche dans le schéma ci-dessous : public static void main(String[] args) {

SetOfBool set = new SetOfBool( );set.add(true);set.add(false);set.add(true);System.out.println( set.conjonction( ) );…

 public boolean conjonction( ) { boolean c = true;int index = 0;while (index < this.lesBooleens.length) {

c = c && this.lesBooleens[ index ];index = index + 1;

}

return c;}

 Notez le rôle de l’index dans le code de conjonction. On accède à une case d’un tableau via unindex et vu que nous souhaitons traiter tous les éléments du tableau on décide de l’initialiser à 0, del’incrémenter à chaque pas de boucle pour passer à la case suivante, et de continuer tant qu’on n’aura pastraité toutes les cases du tableau.

Sur cet exemple notre programme semble fonctionner convenablement. Mais comment nous enassurer ? Le tester sur des tas d’exemples nous rassurerait sûrement sur sa justesse, mais il demeurerait undoute, celui de l’existence d’un contre-exemple parmi les cas non testés. Seule une preuve nousrassurerait définitivement.

Pour prouver notre programme nous pouvons exhiber un invariant de notre boucle : « après i pas dela boucle while, index  vaut i  et c  vaut la conjonction des index  premiers Booléens delesBooleens ». Cette affirmation est vraie après le premier pas de boucle puisque index vaut 0 avantla boucle et est incrémenté de 1 en fin de boucle et conjonction est affectée durant ce premier pas de

 boucle à (true && lesBooleens[0]). Supposons la propriété vraie jusqu’à un certain nombre i de pas de boucles et prouvons qu’elle est alors également vérifiée après (i+1)  pas. Au début du(i+1)ème  pas, index  vaut i  et conjonction vaut la conjonction des index  premiers Booléens delesBooleens . Par conséquent, après l’affectation c = c && this.lesBooleens[index], c vaut la conjonction des (i+1) premiers Booléens de lesBooleens. De plus, index est incrémentéde 1 et sa valeur passe donc à (i+1), soit le nombre de pas de boucles accomplis.

index est incrémentée dans chaque pas de boucle. On va donc sortir de la bouclewhile

 dès que(index==this.lesBooleens.length) et l’invariant nous assure qu’alors c vaut la conjonctiondes this.lesBooleens.length premiers Booléens de lesBooleens.

truefalsetrueset

lesBooleens

this

c

index

true

0

truefalsetrueset

lesBooleens

this

c

index

true

1

truefalsetrueset

lesBooleens

this

c

index

false

2

truefalsetrueset

lesBooleens

this

c

index

false

3

Page 69: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 69/199

Les  concepts de programmation  Programmation Les boucles while  [email protected] – B227 

67 

On pourrait croire que cette preuve a été faite bien après l’écriture du programme mais on n’écrit pasun programme au hasard en tâchant ensuite de le prouver. L’idée de la preuve découle naturellement del’idée qui a conduit au programme. L’invariant existe parce que le concepteur du programme a écrit soncode de façon à ce que cet invariant soit vérifié.

Le code que nous venons de voir est correct. Par contre, on peut améliorer sa rapidité de réponse.Supposons que le premier Booléen du tableau soit false. Peu importe la valeur des autres Booléensdans le tableau, la conjonction sera forcément false. Pourtant notre algorithme continuera de considérertous les autres Booléens. Nous pouvons améliorer notre programme en arrêtant de considérer davantagede Booléens dès que la conjonction et fausse (et donc en ne continuant d’en considérer davantage que si c est vraie).

Exemple  public boolean conjonction( ) {

 boolean c = true;int index = 0;while (c && (index < this.lesBooleens.length)) {

c = c && this.lesBooleens[ index ];

index = index + 1;}return c;

}

Erreurs classiques 

A présent que nous avons un programme correct et relativement rapide, regardons quelques versionserronées afin d’illustrer les erreurs les plus classiques concernant des boucles while.

Important !Vérifier l’initialisation des variables, la condition, ainsi que le corps de la boucle afin des’assurer de la terminaison et de l’exactitude du programme.

Le compilateur nous avertirait d’un oubli d’une initialisation, notamment si nous oublions d’initialiserla variable index. Par contre, le compilateur n’a aucun moyen de savoir si la valeur utilisée pourl’initialisation est la bonne. C’est notre rôle que de nous en assurer. Dans l’exemple ci-dessous index aété par erreur initialisée à 1 et le premier Booléen du tableau ne sera par conséquent pas considéré.

Exemple ERRONE !!!  public boolean conjonction( ) {

 boolean c = true;int index = 1; //   mauvaise initialisation while (c && (index < this.lesBooleens.length)) {

c = c && this.lesBooleens[ index ];index = index + 1;

}return c;

}

Page 70: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 70/199

 

68 

Les  concepts de programmation  Programmation Les boucles while  [email protected] – B227 

 Nous pourrions également « oublier » d’incrémenter index  à chaque pas de boucle. Comme lacondition de la boucle while est initialement vraie, et que l’index n’évoluerait pas, notre seul espoir desortir de la boucle serait que this.lesBooleens[0]. Dans le cas contraire, le nombre de pas de

 boucle serait infini. La condition demeurerait vraie quel que soit le nombre de pas de boucle accomplis eton ne sortirait jamais de cette boucle.

Exemple ERRONE !! !  public boolean conjonction( ) {

 boolean c = true;int index = 0;while (c && (index < this.lesBooleens.length)) {

c = c && this.lesBooleens[ index ];// oubli de l’incrémentation   boucle infinie 

}return c;

}

Une mauvaise condition peut également conduire à une boucle infinie ou à une erreur comme dansl’exemple ci-dessous dans lequel l’index va aller au-delà des limites de validité. La tentative d’accès à descases du tableau avec un index hors limites va conduire à un bug à l’exécution.

Exemple ERRONE !! !  public boolean conjonction( ) {

 boolean c = true;int index = 0;while (c && (index >= 0)) { // mauvaise condition 

c = c && this.lesBooleens[ index ];index = index + 1;

}return c;

}

Bien d’autres erreurs sont possibles. Dans l’exemple ci-dessous la condition doit être corrigée enremplaçant « < » par « <= » car en l’état le dernier Booléen du tableau n’est pas pris en compte.

Exemple ERRONE !! !  public boolean conjonction( ) { boolean c = true;int numeroPasDeBoucle = 1;

while (c && (numeroPasDeBoucle<this.lesBooleens.length)) { //// mauvaise condition : le dernier Booléen n’est pas considéré c = c && this.lesBooleens[ numeroPasDeBoucle-1 ];numeroPasDeBoucle = numeroPasDeBoucle + 1;

}return c;

}

Page 71: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 71/199

Les  concepts de programmation  Programmation Les boucles while  [email protected] – B227 

69 

Enfin, revenons sur l’évaluation paresseuse des opérateurs &&  et ||. Comme nous l’avons vu,l’évaluation d’une expression A&&B commence par l’évaluation de A et B n’est évaluée QUE SI A vauttrue (puisque si A vaut false, A&&B vaut false quelle que soit la valeur de B).

Cette évaluation paresseuse est cruciale pour certains tests comme dans l’exemple ci-dessous où l’on

est assuré qu’il n’y aura pas d’accès à this.lesEntiers[i] avec un i trop grand car on test avant (en le mettant à gauche) que l’index demeure dans les limites de validité. Si on remplaçait la condition par((this.lesEntiers[i]!=x)&&(i<this.lesEntiers.length))  on pourrait sortir dutableau et faire planter le programme.

Exemple  public class SetOfInt {

 private int[] lesEntiers; /**

* @return Retourne true si x figure dans l’ensemble (sinon retourne false)

*/

 public boolean present( int x) {int i = 0;while ((i<this.lesEntiers.length) && (this.lesEntiers[i]!=x)) {

i = i + 1;}return (i<this.lesEntiers.length);

// si i< this.lesEntiers.length c’est qu’on a trouvé x  }

…}

Résumé-  Une boucle while  (cond) {corps}  permet de répéter une action (corps) tant qu’une

condition (cond) est vérifiée.-  cond est d’abord évaluée et on n’évalue corps une première fois que si cond vaut true.

-  cond est réévaluée après chaque évaluation du corps de boucle afin de savoir si on évalue le corpsune fois de plus.

-  Si la condition demeure vraie à tout jamais, la boucle est infinie. Afin d’éviter cela, mais aussi des’assurer  de la complétude du traitement il convient d’être vigilent à (1) l’état des variables avant la

 boucle, à (2) la condition de la boucle, et à (3) l’évolution des valeurs des variables dans le corps.

Exercice PR011 p. 161  Corrigé p. 176 

Exercice PR012 p. 162  Corrigé p. 176 

Exercice PR013 p. 163  Corrigé p. 176 

Page 72: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 72/199

 

70 

Les  concepts de programmation  Programmation Méthodes de classe (static)  [email protected] – B227 

3.17.  Méthodes de classe (static)

Ça ne vous a pas échappé, la méthode principale main  est static  alors que les méthodesd’instances ne le sont pas. Mais que veut dire ce static ? static  veut dire « de classe », par

opposition à « d’instance ». Si une méthode d’instance (non static ) est appelée sur une instance, uneméthode de classe est appelée sur la classe.

Des méthodes d’instance vous en avez vues pas mal. Vous commencez à les cerner. Ellescorrespondent à des services qu’on peut demander à un objet et il est donc normal de les appeler sur unobjet. Au sein du code d’une méthode d’instance, this désigne l’objet sur lequel la méthode d’instanceest appelée. Une méthode d’instance peut donc, via this, accéder à l’état et aux autres méthodes del’objet sur lequel elle est appelée.

A l’inverse, une méthode static  n’est pas appelée sur un objet et elle n’a donc pas de

paramètre this. main notamment est static  et indiquer this dans main n’a pas de sens. Etant la première méthode appelée, aucune instance d’objet n’a encore pu être créée et main ne peut donc pas

être appelée sur un objet.Mais main n’est pas un cas unique. Par exemple la fonction floor qui calcule la partie entière d’un

double  n’aurait que faire d’un objet. Cette fonction, comme beaucoup d’autres fonctionsmathématiques, figure dans la classe Math. On invoque les méthodes de classe en les préfixant du

nom de la classe où elles se trouvent. Ainsi, si vous avez un double d dont vous souhaitez connaîtrela partie entière vous pouvez faire appel à Math.floor( d ). Les méthodes de classe n’étant pasappelée sur des objets, les seules données qu’elles manipulent sont précisées explicitement en paramètre,comme ici l’argument de type double.

Vous avez déjà utilisé d’autres méthodes static  . En effet, toutes les fonctions permettant deréaliser des saisies sont des méthodes static regroupées dans la classe Clavier.

Les méthodes que vous écrirez seront presque toujours des méthodes d’instance, mais vous serez sansdoute amenés à écrire quelques méthodes static. Par exemple, si vous écrirez une méthode main quiest longue (et du coup devient moins lisible), vous pourriez vouloir la découper en plusieurs méthodescorrespondant aux grandes étapes du traitement. Vous pourriez aussi vouloir factoriser un petit calcul quine dépend que de ses paramètres, comme par exemple le calcul du discriminant en fonction descoefficients d’un polynôme de second degré, plutôt que de refaire ce calcul en divers endroits de votrecode.

Résumé-  Les méthodes de classe (static) ne sont pas appelées sur des instances et elles n’ont donc pasde paramètre this.

-  On invoque une méthode de classe en préfixant son nom de celui de la classe où elle se trouve(ex. : Math.floor(x) pour appeler la méthode floor de la classe Math).

Exercice PR014 p. 164  Corrigé p. 176 

Page 73: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 73/199

Les  concepts de programmation  Programmation Decomposer   [email protected] – B227

 

71 

3.18.  Decomposer

 Nous avons vu, notamment dans la section sur l’alternative simple, qu’il est possible d’écrire plusieursalgorithmes plus ou moins lisibles répondant aux mêmes spécifications. Un moyen souvent utilisé pour

améliorer la lisibilité consiste à décomposer la tâche à réaliser en un ensemble de sous-tâches, lesquelles pourront à leur tour être décomposées en des sous-tâches si elles sont encore conséquentes, et ce jusqu’àobtenir des tâches qui peuvent aisément être traitées. Au lieu de devoir écrire un unique algorithme longet compliqué, le travail consistera en la réalisation d’un ensemble d’algorithmes plus simples et lisibles.Un compromis doit être trouvé : si on décompose trop peu on aura des algorithmes longs et compliqués,et si on décompose trop nous n’aurons que des algorithmes de quelques lignes mais il sera ardu decomprendre comment ces algorithmes s’appellent entre eux pour réaliser la tâche initiale.

Un des critères est la longueur. On considère généralement qu’un algorithme de plusieurs dizaines delignes doit être découpé en sous-algorithmes. Mais c’est avant tout la perception d’une tâche comme étantunitaire qui doit marquer l’arrêt de la décomposition. On ne décompose une tâche que si on perçoit

 plusieurs étapes pour la réaliser.

Une tâche doit d’autant plus être décomposée si elle comporte une sous-tâche réalisée plusieurs fois :isoler la sous-tâche permet de factoriser le code et améliore la réutilisabilité (il y a des chances pour quevous puissiez réutiliser le code d’une sous-tâche dans d’autres programmes). Dans l’exemple ci-dessous ilfaut lire en détails le programme de gauche pour être assuré de sa correction et pour comprendre qu’ilcherche d’abord à isoler le minimum puis à isoler le maximum. Dans la version de droite cette stratégieest plus claire et les fonctions min et max pourront potentiellement être réutilisés.

 public class Tri {/**

* modifie le tableau t de sorte que ses trois

* premiers entiers apparaissent dans l’ordre

* croissant.

* @param t un tableau comportant 3 entiers

*/

 public static void  triPeuLisibleDe3Entiers(int[] t){

int min, med, max ;if (t[0]<t[1]) {

if (t[0]<t[2]) {min = t[0] ;if (t[1]<t[2]) {

max = t[2] ;}else {

max = t[1] ;}

}else {

min = t[2] ;max = t[1] ;

}}else {

if (t[1]<t[2]) {min = t[1] ;if (t[0]<t[2]) {

max = t[2] ;}else {

max = t[0] ;}

}else {

min = t[2] ;max = t[0] ;

}}med = t[0}+t[1]+t[2]-min-max ;t[0]=min ;t[1]=med ;t[2]=max ;

}} 

 public class Tri {/**

* modifie le tableau t de sorte que ses trois

* premiers entiers apparaissent dans l’ordre

* croissant.

* @param t un tableau comportant 3 entiers

*/

 public static void  triLisibleDe3Entiers(int[] t){

int min, med, max ;min = Tri.min( t[0], Tri.min(t[1],t[2])) ;max = Tri.max( t[0], Tri.max(t[1],t[2])) ;med = t[0]+t[1]+t[2]-min-max ;t[0]=min ;t[1]=med ;t[2]=max ;

}

/**

* @param x un entier quelconque

* @param y un entier quelconque

* @return le plus petit des deux entiers

*/

 public static int min(int x, int y) {if (x<y) {

return x ;}else {

return y;}

}

/**

* @param x un entier quelconque

* @param y un entier quelconque

* @return le plus grand des deux entiers

*/

 public static int max(int x, int y) {if (x<y) {

return y ;}else {

return x;}

}} 

Page 74: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 74/199

 

72 

Les  concepts de programmation  Programmation Utiliser des constantes  [email protected] – B227 

3.19.  Utiliser des constantes

Les constantes ne sont ni plus ni moins que des variables dont la valeur n’évolue pas. Elles sontdéclarées en début de classe en dehors de toutes fonction/procédure, portent les modificateurs final etstatic, et sont initialisées dès leur déclaration (on ne peut bien sûr plus les affecter par la suite).

Si on précise final c’est pour indiquer que la valeur ne pourra pas être modifiée. La précision destatic s’explique par le fait qu’on ne souhaite pas que chaque instance de la classe ait son propreexemplaire (si on n’indique pas static il s’agit d’une variable d’instance) car il est inutile de dupliquercette information, ce serait une pure perte de mémoire et une source potentielle d’incohérences.Une variable static est une variable de classe, créée en un unique exemplaire et mémorisée au niveaude la classe (plutôt que dupliquée pour chaque instance).

Mieux vaut définir des constantes nommées plutôt que de manipuler directement leurs valeurs. Eneffet, leurs noms explicites facilitent grandement la lecture. Jugez par vous-même sur l’exemple suivant.

Exemple  public class Vetement {

… public double tarif() {

…if (this.code==782234) {

prix = prix * 0.5;}…if (id==168099954678201) {

autorisation = true;}…rayon = 0.5 * diametre;…

}}

 public class Vetement {

 public static final int CODE_CHEMISE_ETE = 782234; public static final double RABAIS_SOLDES = 0.5; public static final int ID_PATRON=168099954678201;

 public double tarif() {…if (this.codeArticle== Vetement.CODE_CHEMISE_ETE){

prix = prix * Vetement.RABAIS_SOLDES;}…if (num== Vetement.ID_PATRON) {

autorisation = true;}…rayon = 0.5 * diametre;…}

De plus, l’usage de constantes facilite la maintenance. Supposons que nous ayons bêtement utilisédirectement la valeur 3.14 dans notre code plutôt que de déclarer une constante PI ayant cette valeur.Si nous nous apercevons que la précision de nos calculs n’est pas suffisante, nous devrions remplacerdans notre algorithme toutes les valeurs 3.14 qui correspondent à la valeur de PI et uniquement elles (il peut y avoir d’autres 3.14 dans notre algorithme qui font référence à une température, un prix, ou toutautre chose, tout comme dans le programme ci-dessus où les 0.5 ne font pas tous référence à un rabais)

 par une meilleure approximation (3.1415926535 par exemple). L’utilisation d’une constante simplifiegrandement cette mise à jour puisqu’il suffit de modifier sa déclaration en précisant la nouvelle valeur.

Certaines classes fournies avec Java possèdent des constantes. C’est le cas par exemple de la classeMath qui contient les constantes PI et E.

Exemple  public class Cercle {

 private Point centre ; private double rayon ;

 public double getPerimetre() {return (2*(Math.PI*this.rayon));

}…

}

Convention typographique 

Les noms de constantes ne sont composés que de majuscules, les termes étant séparés par un caractère

de soulignement « _ » (cf. les exemples ci-dessus).

Exercice PR015 p.165  Corrigé p. 176 

Page 75: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 75/199

Les  concepts de programmation  Programmation Les boucles do…while  [email protected] – B227 

73 

3.20.  Les boucles do…while 

do {

<corpsDeLaBoucle> } while (<condition>);

Si au moins un pas de boucle doit être effectué on peut utiliser une boucle do…while plutôt qu’une boucle while. Le corps d’une boucle while peut ne jamais être exécuté si la condition est initialementfausse. Ce n’est pas le cas avec les boucles do…while car la condition n’est évaluée qu’après chaque pasde boucle.

Les boucles do…while n’étendent pas l’expressivité : toute boucle do…while peut être remplacée par une boucle while. Cependant, la nuance sémantique peut-être utilisée pour apporter plus de clarté.

Une utilisation classique est la vérification d’une saisie. Si l’utilisateur se trompe on va l’inviter àsaisir de nouveau mais pour pouvoir tester s’il s’est trompé il faut bien qu’une première saisie ait eu lieu.

Si on compare les codes de saisie d’une note sur 20 avec les deux types de boucles (cf. ci-dessous) on voitqu’avec une boucle while on est obligé de « faire comme si » l’utilisateur avait déjà fait une erreur desaisie pour pouvoir rentrer au moins une fois dans la boucle, ce qui n’est pas très naturel puisqu’aucunesaisie n’a encore eu lieu.

Exemple  public class Saisies { public static double saisieNoteWhile() {

double note = 0.0; boolean erronee = true ;while ( erronee ) {System.out.println("Veuillez saisir une note (entre 0 et 20)");

note = Clavier.lireDouble();erronee = (note<0.0 || note>20.0);if (erronee) {System.out.println("Erreur de saisie");

}}return note;

}

 public static double saisieNoteDoWhile() {double note = 0.0;do {

System.out.println("Veuillez saisir une note (entre 0 et 20)");note = Clavier.lireDouble();if (note<0.0 || note>20.0) {System.out.println("Erreur de saisie");

}} while (note<0.0 || note>20.0); return note;

}

Exercice PR016 p. 166  Corrigé p. 176 

Exercice PR017 p. 167  Corrigé p. 176 

Exercice PR018 p. 168  Corrigé p. 176 

Page 76: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 76/199

 

74 

Les  concepts de programmation  Programmation Incrémentations et affectations  [email protected] – B227 

3.21.  Incrémentations et affectations

Comme nous l’avons vu, =  est l’opérateur d’affectation, à ne surtout pas confondre avec le testd’égalité ==. Il arrive très fréquemment que l’affectation soit utilisée pour incrémenter/décrémenter une

variable. C’est une opération si fréquente que Java possède des opérateurs dédiés, ++et --. Ainsi, x++; est équivalent à x=x+1; et x--; est équivalent à x=x-1; .

De nouveaux opérateurs (+=, -=, *=, /= et %=) permettent de réaliser une opération (+, -, *, / ou %)avant d’affecter le résultat comme illustré dans le tableau ci-dessous. Notez que tous ces opérateurs nesont que du sucre syntaxique, elle n’augmente en rien l’expressivité du langage puisque nous pourrionsnous en passer en utilisant leur équivalent.

Equivalent àx += y ; x = x + y ;

x -= y ; x = x - y ;

x *= y ; x = x * y ;

x /= y ; x = x / y ;x %= y ; x = x % y ;

x++ ; x = x + 1 ;

x-- ; x = x - 1 ;

Exemples  public class SetOfInt {

 private int[] lesEntiers; /**

* @return Retourne true si x figure dans l’ensemble (sinon retourne false)

*/

 public boolean present( int x) {int i = 0;while ((i<this.lesEntiers.length) && (this.lesEntiers[i]!=x)) {

i++; // Equivalent à i = i + 1;  }}return (i<this.lesEntiers.length);

}…}

 public class SetOfBool {  private boolean[] lesBooleens;

/*** @return Si l’ensemble est vide, retourne true, sinon, retourne la

* conjonction des Booléens de l’ensemble de rang impair (conjonction du* premier avec le troisième, le cinquième, …)*/

 public boolean conjonctionRangImpair( ) { boolean conjonction = lesBooleens[0];int index = 0;while (index < lesBooleens.length) {

conjonction = conjonction && lesBooleens[index];index += 2; // Equivalent à index = index + 2;

}return conjonction;

}…}

Page 77: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 77/199

Les  concepts de programmation  Programmation Les boucles for  [email protected] – B227 

75 

3.22.  Les boucles for 

Les boucles while permettent de répéter une action tant qu’une certaine condition est respectée. Ilarrive fréquemment que la boucle soit utilisée pour réaliser une action sur un ensemble d’éléments

clairement identifié, la condition n’exprimant que le fait de ne pas encore avoir fait l’action sur tous leséléments à considérer. Par exemple, si on doit afficher un tableau on va afficher un à un ses éléments. Onva répéter une action sur chaque élément du tableau. En langage naturel nous aurions dit « pour toutélément du tableau, afficher l’élément ». Il serait donc plus naturel d’utiliser une boucle for  qu’une

 boucle while.

for (<expInit> ; <conditionContinuation> ; <expPostPas>) {<corpsDeLaBoucle> 

}

est sémantiquement équivalent à :

<expInit>;while (<conditionContinuation>) {

<corpsDeLaBoucle> <expPostPas> 

}

Une boucle for étant très proche d’une boucle while, on retrouve les mêmes points de vigilance.-  L’initialisation (<expInit>).-  La condition de continuation (<conditionContinuation>). Il faut en particulier s’assurer

qu’on sortira assurément de la boucle quelle que soit la donnée. Attention également au fait qu’ils’agisse d’une condition de continuation (ce n’est pas une condition d’arrêt), on continue de fairedes pas de boucle tant que cette condition est vérifiée. Notamment, UN  pas tout au plus seraréalisé si on précise un test d’égalité au lieu d’un test d’infériorité ou de supériorité !!!

-  Les modifications à apporter pour passer au prochain cas à traiter (<expPostPas>).

Les boucles for  n’étendent pas l’expressivité du langage. Comme indiqué ci-dessus, on pourraitutiliser une boucle while à la place d’une boucle for et vice-versa. C’est uniquement pour gagner enlisibilité que nous emploierons ces deux types de boucles :

-  Si on connait le nombre de pas de boucles qui seront effectués, on emploiera une boucle for.

-  Si au contraire il est impossible de savoir combien de pas de boucle seront nécessaires, onutilisera une boucle while.

Par exemple, afficher les éléments d’un tableau, faire l’addition des nombres d’un tableau, inverserl’ordre d’un tableau, … sont autant de tâches pour lesquelles le nombre de pas de boucles nécessaires estconnu. Une boucle for  sera dès lors plus judicieuse. A l’inverse, il existe de nombreuses tâches pourlesquelles le nombre de pas de boucle ne peut pas être déterminé avant la boucle et pour lesquelles nous

utiliserons une boucle while : déterminer si un élément est présent dans un ensemble (il se peut quel’élément soit le premier auquel cas un seul pas de boucle sera nécessaire, ou que l’élément soit absent,auquel cas on s’en apercevra après avoir consulté tous les éléments de l’ensemble), vérifier si tous leséléments d’un ensemble ont une certaine propriété (dès qu’on trouve un élément qui ne la vérifie pas on

 peut s’arrêter), retourner tous les éléments d’une suite croissant Ui inférieurs à une certaine borne (pourcertaines suite il est difficile de déterminer à partir de combien d’éléments on va dépasser la borne), …

Avant d’écrire du code, il faut toujours se poser la question « comment personnellement je fais » en semettant face à un exemple afin d’esquisser d’une stratégie. Il faut également se demander « quand latâche est elle finie ? », question essentielle pour déterminer (1) quelle boucle employer et (2) quelles sontles conditions de continuation. Le très court chapitre 11 p. 139 vous donne davantage derecommandations.

Important !

Ne jamais mettre d’instruction return dans le corps d’une boucle.

Page 78: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 78/199

 

76 

Les  concepts de programmation  Programmation Les boucles for  [email protected] – B227 

La recommandation ci-dessus peut paraître extrême. On peut en effet écrire du code avec des return dans des boucles sans que le compilateur nous insulte et sans qu’il n’y ait de problème à l’exécution.Toutefois, un return renvoie le résultat de la fonction, et par conséquent fait sortir de la boucle (on sortmême de la fonction). Du coup, mettre un return dans une boucle c’est :

-  Une source importante d’erreurs. Surtout lorsqu’on ne maîtrise pas parfaitement la sémantique del’instruction return.

-  Rendre le code moins explicite. La situation dans laquelle on fait le return devrait apparaîtredans la condition de continuation. On devrait connaître à la lecture de la condition de continuationdans quels cas on continue/on s’arrête, et ne pas découvrir dans le corps, après parfois pas mal delignes de code, qu’il existe d’autres situations dans lesquelles on interrompt le traitement.

Regardons cela sur deux variantes peu lisibles de l’exemple ci-dessous.

Exemple /*** @param t, un tableau contenant au moins un entier* @param seuil, un entier* @return seuil si tous les entirs de t sont inférieurs ou égaux à seuil.

* Sinon, retourne le premier entier de t supérieur strictement à seul.*/

 public static int premierPlusGrand( int[] t, int seuil) {int index = 0;while ((index<t.length) && (t[index]<=seuil)) {

index++;}if (index<t.length) {

return t[index];}else {

return seuil;

}}

Dans les deux versions ci-dessous, la lecture de la condition de continuation laisse penser qu’on nes’arrêtera pas tant qu’on n’a pas atteint la taille du tableau. Ce n’est qu’à la lecture du corps qu’ondécouvre qu’on s’arrête également si on trouve un élément du tableau plus grand que seuil. De plus, un

 bref regard pourrait laisser croire qu’on retourne dans tous les cas seuil puisque le dernier return n’est dans aucune conditionnelle.

Versions peu lisibles public static int premierPlusGrandPeuLisible( int[] t, int seuil) {

int index = 0;while (index<t.length) {

if (t[index]>seuil) {return t[index];

}index++;

}return seuil;

} public static int premierPlusGrandPeuLisible2( int[] t, int seuil) {

for (int index=0; index<t.length; index++) {if (t[index]>seuil) {

return t[index];}

}return seuil;}

Page 79: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 79/199

Les  concepts de programmation  Programmation Les boucles for  [email protected] – B227 

77 

Remarque

Il est possible de déclarer la variable principale d’une boucle for dans <expInit> comme dansl’exemple premierPlusGrandPeuLisible2. La portée de la variable est alors limitée au corpsde la boucle for (sur l’exemple, index n’existe pas en dehors de la boucle for). 

Important !

Ne jamais modifier la variable d’une boucle for dans le corps de la boucle.

Comme pour la recommandation précédente, deux raisons expliquent cette règle.-  La lisibilité. A la lecture de la déclaration de la boucle for  nous devrions être en mesure de

connaître toutes les valeurs que la variable prendra (ce qui n’est pas possible si des modificationsde cette variable ont lieu dans le corps).  

-  Limiter les risques d’erreurs. C’est <expPostPas> qui fixe comment la variable évolue de pasen pas. Si on modifie la variable dans le corps on peut par exemple « sauter » des pas comme dansl’exemple ci-dessous. 

Exemple ERRONE !!! /*** @param t, un tableau contenant au moins un entier.* @return la somme des entiers de t.*/

 public static int somme( int[] t) {int somme = 0;for (int i=0 ; i<t.length ; i++) {

somme = somme + t[i];i++; // Incrémentation en trop ! i sera incrémentée 2 fois

// On fera un pas avec i==0, puis un avec i==2, puis i==4…

}

return somme;}

Résumé-  Dupliquer du code (faire un copier-coller à divers endroits) augmente la probabilité d’erreurs, rend

la maintenance plus délicate, et réduit la lisibilité et la réutilisabilité. Si un code est utile endifférents endroits il faut en faire une méthode. Plus généralement, il faut décomposer soncode en tâches plus petites, donc plus simples à traiter.

-  Mieux vaut déclarer des constantes que d’utiliser des valeurs littérales. On augmente lalisibilité et la maintenance est simplifiée.-  Si on doit répéter une action un nombre indéterminé de fois, potentiellement nul, mieux vaut

utiliser une boucle while.-  Si on doit répéter une action un nombre indéterminé de fois, mais qu’au moins un pas est

nécessaire comme par exemple pour vérifier une saisie, on peut utiliser une boucle do…while.-  Si on doit répéter une action un nombre déterminé de fois, mieux vaut utiliser une boucle for.-  Il est recommandé de ne pas mettre d’instruction return dans le corps d’une boucle.-  Ne jamais modifier la variable d’une boucle for dans le corps de la boucle.

Exercice PR019 p. 169  Corrigé p. 176 

Exercice PR020 p. 170  Corrigé p. 176 

Page 80: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 80/199

 

78 

Les  concepts de programmation  Programmation Les branchements / choix multiples switch  [email protected] – B227 

3.23.  Les branchements / choix multiples switch 

On retrouve fréquemment des structures alternatives simples imbriquées. Il arrive en effet assezsouvent d’être confronté à traiter les différentes valeurs que peut prendre une expression.Les branchements sont alors un moyen d’apporter plus de clarté au code en précisant les traitements àréaliser face à chacun des cas énumérés Si  l’expression est de type String, int  ou convertissableimplicitement en int comme char par exemple.

Exemple switch (<exp>) { 

case <val0> : <blocCas0> ; break ; case <val1> : <blocCas1> ; break ; case <val2> : case <val3> : case <val4> : <blocCas234> ; break ;case <val5> : <blocCas5> ;case <val6> : <blocCas56> ; break ;

case <val7> : <blocCas7> ; break ;default  : <blocCasParDefaut> ; break ;

}

Ce branchement est équivalent à l’imbrication de conditionnelles simples ci-dessous. Nous pouvionsdonc déjà exprimer tout ce qui est exprimable avec cette nouvelle structure de contrôle et nous pourrionsnous passer de cette nouveauté si la clarté du code n’était pas importante (Mais la lisibilité du code étantimportante nous emploierons cette nouvelles structure grammaticale si l’intérêt s’en fait sentir).

Exemple if (<exp>==<val0>) { 

<blocCas0> }else {

if (<exp>==<val1>) { <blocCas1> 

}else {

if (((<exp>==<val2>)||(<exp>==<val3>))||(<exp>==<val4>)){ <blocCas234> 

}else {

if ((<exp>==<val5>) || (<exp>==<val6>)) {if (<exp>==<val5>) { 

<blocCas5> }<blocCas56> 

}else {

if (<exp>==<val7>){ <blocCasi> 

}else {

<blocCasPasDefaut> }

}

}}}

String ou int ou type convertissable implicitement en int 

Valeurs du même type que <exp> 

Page 81: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 81/199

Les  concepts de programmation  Programmation Les branchements / choix multiples switch  [email protected] – B227 

79 

Remarque

Seule une marque break permet de ne pas poursuivre par l’évaluation des blocs des autres cas. 

 Notons que le premier bloc exécuté est celui du premier cas correspondant à la valeur actuelle de<exp>  mais que l’évaluation des instructions se poursuit jusqu’à la rencontre d’une marque

 break. Ainsi, sur notre exemple, si <exp> vaut <val6>, seul le bloc <blocCas56> sera évalué. Si par contre <exp> vaut <val5>, le bloc <blocCas5> sera évalué avant de poursuivre par l’exécutiondu bloc <blocCas56>. La première marque break qu’on rencontre après le cas <val5> est en effetsituée après le bloc <blocCas56>. Le branchement ci-dessous est donc équivalent. L’usage desmarques break dans la première version permet cependant d’éviter des duplications de blocs inutiles. La

 première version est donc nettement préférable puisque du code dupliqué rend la maintenancebeaucoup moins aisée.

Exemple switch (<exp>) { 

case <val0> : <blocCas0> ; break ; case <val1> : <blocCas1> ; break ; 

case <val2> : <blocCas234> ; break ; case <val3> : <blocCas234> ; break ; case <val4> : <blocCas234> ; break ;case <val5> : <blocCas5> ; <blocCas56> ; break ;case <val6> : <blocCas56> ; break ;case <val7> : <blocCas7> ; break ;default : <blocCasParDefaut> ; break ;

}

La clause default est facultative. Si elle est précisée, le blocCasParDefaut  sera évalué si lavaleur de <exp> ne correspond à aucun des cas précédemment listés.

Les blocs peuvent bien évidemment comporter des conditionnelles simples, voire des branchements.

Bien sûr, si il n’y a que 2 à 3 cas, mieux vaut utiliser des alternatives simples. De même, nous nesubstituerons pas par un switch  une imbrication d’alternatives simples ayant des conditions qui nevisent pas à isoler des valeurs potentielles d’une expression. L’exemple ci-dessous illustre qu’il peut-êtretoutefois bien plus clair d’utiliser un switch qu’une imbrication de conditionnelles simples.

Exemple  public class Date {

 private int jour, mois, annee;…

 public String getNomMois() {String nom;switch (this.mois) {

case 1 : nom=“Janvier” ;  break ;

case 2 : nom=“Fevrier” ;  break ;case 3 : nom=“Mars” ;  break ;case 4 : nom=“Avril” ;  break ;case 5 : nom=“Mai” ;  break ;case 6 : nom=“Juin” ;  break ;case 7 : nom=“Juillet” ;  break ;case 8 : nom=“Aout” ;  break ;case 9 : nom=“Septembre” ; break ;case 10 : nom=“Octobre” ;  break ;case 11 : nom=“Novembre” ;  break ;default : nom=“Decembre” ;  break ;

}return nom ;

}} 

Version équivalente mais comportant des duplications ( à éviter !!!) 

Page 82: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 82/199

 

80 

Les  concepts de programmation  Programmation Les branchements / choix multiples switch  [email protected] – B227 

Le programme équivalent ci-dessous est bien moins lisible en dépit des efforts louables d’indentation.Au delà de la clarté, le code utilisant un branchement est moins sujet à erreurs  puisque la probabilitéest grande de se tromper sur l’imbrication des conditionnelles simples (accolades oubliées/mal placées).

Exemple …

 public String getNomMois( ) {String nom ;if (numeroMois==1) {

nom=“Janvier”;}else {

if (numeroMois==2) {nom=“Fevrier”;

}else {

if (numeroMois==3) {nom=“Mars”;

}else {

if (numeroMois==4) {nom=“Avril”;

}

else {if (numeroMois==5) {nom=“Mai”;

}else {

if (numeroMois==6) {nom=“Juin”;

}else {

if (numeroMois==7) {nom=“Juillet”;}else {

if (numeroMois==8) {nom=“Aout”;

}

else {if (numeroMois==9) {nom=“Septembre”;

}else {

if (numeroMois==10) {nom=“Octobre”;

}else {

if (numeroMois==11) {nom=“Novembre”;

}else {nom=“Decembre”;

}}

}}

}}

}}

}}

}return nom ;}

Exercice PR021 p. 171  Corrigé p. 176 

Exercice PR022 p. 172  Corrigé p. 176 

Page 83: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 83/199

Les  concepts de programmation  Programmation Les exceptions  [email protected] – B227 

81 

3.24.  Les exceptions

 Nous avons vu des programmes pour lesquels des conditions doivent être vérifiées sur les données (letableau doit être trié, le paramètre doit être positif, …). On s’expose à des erreurs si on se contente de

supposer que ces conditions sont vérifiées. Utiliser les exceptions est la solution la plus élégante pourdissocier le code lié au fonctionnement normal de celui de gestion des erreurs.

3.24.1.  Réagir face à une exception

Une exception  est un objet créé lorsqu’une situation anormale est détectée. Les messages d’erreurslistés dans le chapitre 9 p. 131 signalent parfois la création d’exceptions et l’absence de réaction face àces exceptions aboutit à l’arrêt prématuré du programme.

Certaines opérations sont susceptibles de créer des exceptions. C’est le cas par exemple de la divisionqui peut créer une ArithmeticException  si le diviseur est nul, ou des opérations de lecture defichiers qui créent une IOException  si on tente de lire au delà de la fin du fichier par exemple.Ces opérations sensibles doivent être placées dans un bloc try  succédé d’un bloc catch  précisant letraitement à effectuer si une exception survient. Un code source gérant les exceptions suit donc le schémasuivant :

// Instructions ne levant pas d’exceptions

try {// Instructions susceptibles de créer une exception

}catch (TypeException e) {

// Instructions de traitement de l’éventuelle exception

}// Instructions ne levant pas d’exceptions

Dans l’extrait de code ci-dessous, le programmeur veut laisser la liberté de saisir des nombres àvirgule flottante en précisant soit une virgule, soit un point comme séparateur. Il tente tout d’abordd’utiliser Double.parseDouble  pour convertir la chaîne lue en un double  sachant que cettefonction requiert un point pour séparateur. Si d’aventure la chaine n’est pas au format requis (un point

 pour séparateur), la fonction Double.parseDouble lève une exception et on gère cette exception enremplaçant la virgule par un point dans la chaîne. Notez qu’il n’était pas du tout obligatoire de passer parla gestion d’exception dans ce cas précis, il n’est donné qu’à titre d’illustration.

Exemple … 

String chaineMasse = Clavier.lireString() ;double masse ;

try {masse = Double.parseDouble( chaineMasse ) ;

}catch( Exception e) {

masse = Double.parseDouble( chaineMasse.replace("," , ".") );}

Page 84: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 84/199

 

82 

Les  concepts de programmation  Programmation Les exceptions  [email protected] – B227 

3.24.2.  Lever une exception

Que faire si on nous appelle avec des paramètres qui ne vérifient pas les conditions desspécifications ? Il est bien souvent impossible de retourner un résultat, tout simplement parce que ça n’a

 pas de sens. Lever une exception est un moyen de signaler le problème au code appelant, charge à lui degérer nos possibles exceptions.

Un sous-programme susceptible de lever une exception doit l’indiquer en indiquant « throws 

Exception » après les paramètres dans son en-entête. Il lève une exception via l’instruction « throw

new Exception("explication des raisons de la levée d’exception") ; ».

Dans l’exemple ci-dessous, la fonction min de setOfInt doit retourner la valeur minimale contenuedans l’ensemble, ce qui n’a pas de sens si l’ensemble est vide. Le code lève par conséquent une exceptionsi l’ensemble ne contient pas au moins une valeur.

Un appel à min ne pourra se faire que dans une clause try…catch vu que cette fonction peut leverdes exceptions.

Exemple  public class SetOfInt {

 private int[] lesEntiers;… public int min( ) throws Exception {

if (this.size()<1) {throw new Exception("Appel a min() sur un ensemble vide");

}int min=this.get(0);for (int i=1; i<this.size(); i++) {

if (this.get(i)<min) {min = this.get(i);

}}return min;

}}

Résumé-  Un branchement (switch) peut avantageusement remplacer une longue imbrication de

conditionnelles simples si l’on a à traiter les différentes valeurs que peut prendre une expressionentière ou de type String.

-  Dans un switch, seul un break  permet de ne pas poursuivre par l’évaluation des blocs desautres cas.-  Lever une exception (via throw new  Exception("texte")) est un moyen élégant de faire

face à une situation imprévue comme le nom respect des conditions exprimées dans lesspécifications. On précise qu’une méthode est susceptible de lever une exception en rajoutantthrows Exception à la fin de son en-tête.

-  L’appel d’une méthode susceptible de lever une exception doit se faire dans une clause try d’untry…catch, la clause catch précisant le traitement à effectuer en cas de levée d’exception.

Page 85: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 85/199

Les  concepts de programmation  Programmation Les fichiers texte séquentiels  [email protected] – B227 

83 

3.25.  Les fichiers texte séquentiels

Si le programme s’arrête prématurément, à cause d’un bug ou parce que l’ordinateur rencontre un problème (surchauffe, coupure d’alimentation, …) les données en mémoire sont perdues. Lesinformations ne peuvent être mémorisées de manière pérenne que dans des fichiers. Nous allons aborder

les « fichiers texte » qui peuvent être couteux en espace mais qui ont le mérite de pouvoir être manipulésen dehors du programme via un simple éditeur de texte. Pour stocker un nombre, par exemple 1234567,7 octets (un par caractère) sont nécessaires (sans compter les séparateurs). En mémoire en revanche, toutest représenté en binaire et tout int par exemple réclamera le même nombre d’octets, quelle que soit lavaleur de cet entier. Par opposition à « fichiers texte », il existe des  fichiers  dits  binaires  qui utilisentcette façon de représenter les données et que nous ne traiterons pas. Ils sont plus compacts mais ne

 peuvent pas être lus dans un simple éditeur de texte. Le qualificatif « séquentiel » tient au mode d’accèsaux données : pour consulter une donnée il faut avoir consulté toutes celles qui la précèdent. Il fautimaginer des données inscrites sur une bande enroulée (des vieilleries comme les cassettes audio ou VHS)et il convient de dérouler la bande si on veut accéder à une donnée précise. Par opposition à « séquentiel »il existe des accès directs indexés, l’analogie étant le DVD le disque dur sur lesquels il est possible

d’accéder directement à une donnée précise si on connait le secteur où elle se trouve. Nous ne traiteronsque de l’accès séquentiel.

3.25.1.  Ecrire dans un fichier texte

Le schéma est toujours le même : on « ouvre » le fichier, on écrit dans ce fichier, puis on le « ferme ».Toutes les opérations de manipulation de fichiers seront mises dans un bloc try…catch  car elles

 peuvent lever des exceptions. Ne vous souciez pas de savoir ce qu’est un PrintWriter, unBufferedWriter ou encore un FileWriter : pour ouvrir un fichier vous recopierez exactement la

 phrase indiquée dans l’exemple en indiquant l’emplacement de votre fichier au lieu de la variablenomFichier. Si vous n’indiquez qu’un nom sans chemin (comme ici "punition.txt") le fichiersera dans le même répertoire que le programme. Si le fichier est dans un autre répertoire il faudra préciser

le chemin mais notez qu’il vous faut utiliser File.separator  comme caractère de séparation desdossiers dans les chemins si vous voulez que votre code puisse être utilisé sur n’importe quel systèmed’exploitation. Par exemple, si vous voulez manipuler un fichier nommé "scores.txt" situé dans lesous-répertoire "donnees" vous préciserez "donnees"+File.separator+"scores.txt".

Attention  : l’ouverture initialise le fichier à vide. Si le fichier existe déjà, son contenu est vidé àl’ouverture. Si par contre il n’existe pas, l’ouverture le crée (pour l’instant à vide).

Exemple import java.io.*; // Pour indiquer l’utilisation des classes de manipulation de

 public class Punition { // fichiers texte.

 public static void  creerPunition(String nomFichier, String ligne, int nbLignes) {try {// Les operations sur les fichiers peuvent lever des exceptions 

// On ouvre le fichier en écriture

Printwriter aEcrire=new PrintWriter(new BufferedWriter(new FileWriter(nomFichier)));// On écrit dans le fichier

for (int i=0; i<nbLignes( ligne );aEcrire.println( ligne );

}// On ferme le fichier

aEcrire.close();}Catch (IOException e) {

System.out.println("Une operation sur les fichiers a leve l’exception "+e);}

} public static void  main(String[] args) {

Punition.creerPunition("punition.txt","Je ne renverserai plus"

+" de café sur le clavier",100) ;}

}

Page 86: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 86/199

 

84 

Les  concepts de programmation  Programmation Les fichiers texte séquentiels  [email protected] – B227 

3.25.2.  Lire un fichier texte

L’accès aux données d’un fichier texte est ici séquentiel. L’ordre des données dans le fichier estdonc primordial et doit être connu. Nous allons prendre pour exemple un fichier nommé "produits.txt" qui contient des informations (le nom, la référence et le prix) sur un certain nombre de produits. Pour

simplifier, il n’y a qu’une information par ligne et nous allons écrire un programme PasChers qui valire ce fichier et afficher les informations sur les articles dont le prix est inférieur à la constante SEUIL.

Début du fichier produit.txt blastrotron1234563.95aquacyclon234567203.99…

Après l’ouverture en lecture d’un fichier texte, un pointeur auquel nous n’avons pas accès désigne la première ligne comme la ligne courante. readLine() est une fonction qui retourne la ligne courante

(une String) et qui passe à la ligne suivante (en mettant à jour le pointeur). Après le premier appel àreadLine()  la ligne courante devient la 2ème, après le second readLine()  la ligne courante est la3ème… et si on fait plus d’appels à readLine() qu’il n’y a de lignes dans le fichier, readLine() retourne null. On peut ainsi détecter la fin du fichier : si readLine() retourne null c’est qu’on aatteint la fin du fichier.

Exemple import java.io.*; // Pour indiquer l’utilisation des classes de manipulation de

// fichiers texte.

 public class PasChers { public static final double SEUIL = 10.0; public static void  afficherPasChers(String nomFichier) {

String nom ; // le nom du produit courant

int reference ;

// la reference du produit courant

double prix ; // le prix du produit courant

try {//Les operations sur les fichiers peuvent lever des exceptions 

// On ouvre le fichier en lecture

BufferedReader aLire = new BufferedReader(new FileReader(nomFichier)) ;

do {// On lit le nom du produit

nom = aLire.readLine() ;// Si readLine() retourne null c’est qu’on a atteint la fin du fichier

if (nom!=null) {// Si on n’a pas atteint la fin du fichier…reference=Integer.parseInt( aLire.readLine()) ;prix=Double.parseDouble( aLire.readLine());if (prix<SEUIL) {// Le produit n’est pas cher   on l’affiche

System.out.println("Nom : "+nom) ;

System.out.println("Reference : "+reference) ;System.out.println("Prix : "+prix+"\n") ;}

}} while (nom !=null) ; // Tant qu’on n’a pas atteint la fin du fichier

// On ferme le fichier

aLire.close() ;}catch (IOException e) {

System.out.println("Une operation sur le fichier "+nomFichier+" a leve l’exception "+e) ;

}} public static void  main(String[] args) {

PasChers.afficherPasChers( "produits.txt" );

}}

Page 87: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 87/199

Les  concepts de programmation  Programmation Les interfaces  [email protected] – B227 

85 

3.26.  Les interfaces

3.26.1.  Des types de données abstrait

Il nous est arrivé de proposer plusieurs implémentations pour un même concept. Par exemple un

rectangle dont les cotés sont parallèles aux axes peut être représenté en mémoire par deux points (dessommets opposés) ou par l’un de ses sommet et la mention de sa largeur et de sa hauteur. Il en résultedeux implémentations, deux classes, mais qui proposent exactement les mêmes services puisqu’il s’agitdu même concept.

L’encapsulation nous a déjà conduits à ne manipuler des concepts qu’au travers de leurs méthodes.L’utilisateur n’est pas intéressé par la représentation mémoire, tout ce qui est important à ses yeux c’estde connaître les services utiles pour manipuler le concept. On fait donc abstraction de l’état. Reste qu’auniveau du langage Java nous n’avons pour l’heure pas d’outils pour véritablement faire cette abstraction.Revenons sur nos implémentations d’un rectangle. Appelons les Rectangle1  et Rectangle2. Onaimerait pouvoir dire que toutes les deux représentent un même concept et qu’elles sont interchangeables.C’est ce qu’offrent les interfaces.

Les interfaces  sont des types de données abstraits (TDA). Donc des types avant tout, lorsqu’ondéclarera une interface c’est un nouveau type de données qu’on introduit. Mais abstraits, dans le sens oùl’on fait abstraction de la représentation mémoire et du code des méthodes. Bref, un type vu uniquementau travers des entêtes des méthodes, la partie intéressante pour l’utilisateur. Abstrait s’oppose à concret, eton ne pourra pas créer d’instances d’une interface, car on n’a pas de constructeur, ce ne sont que desdescriptions incomplètes sans état ni code.

Le fichier d’une interface ressemble à celui d’un classe, mais :-  Avec interface au lieu de class -  Pas de variables d’instance.-  Pas de constructeur.-  Pas de code pour les méthodes.

Une classe C revendique qu’elle implémente une interface I (et devient du coup un sous-type de I) enrajoutant « implements I  » à sa déclaration. Elle s’engage alors à fournir un code pour toutes lesméthodes dont les entêtes sont cités dans l’interface I.

Exemple  public interface Rectangle {

 public double getLargeur(); public double getHauteur(); public double getBordGauche(); public double getBordDroit(); public double aire(); public  boolean dans(Rectangle r);} 

 public class Rectangle1 implements Rectangle {

 private Point basGauche, hautDroit;

 public Rectangle1(double gauche, double droit,double bas, double haut) {

this.basGauche = new Point(gauche, bas);this.hautDroit = new Point(droit, haut);

}

 public double getLargeur() {return this.getBordDroit()-this.getBordGauche();

}

 public double getHauteur() {return this.hautDroit.getOrdonnee()-

this.basGauche.getOrdonnee();}

 public double getBordGauche() {return this.basGauche.getAbscisse();

}

 public double getBordDroit() {return this.hautDroit.getAbscisse();

}

 public double aire() {return this.getLargeur()*this.getHauteur();

} public  boolean dans(Rectangle r) {

…}}

Page 88: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 88/199

 

86 

Les  concepts de programmation  Programmation Les interfaces  [email protected] – B227 

Comme nous venons de l’indiquer, une classe qui implémente une interface implique un lien de sous-typage. La classe est un sous-type de l’interface qu’elle implémente. De plus, si A est un sous-type deB, alors une expression de type A est aussi de type B. C’est ce qu’on appelle la règle de  subsomption etc’est elle qui permet une conversion implicite du sous-type vers le type. Par conséquent, une référencede type Rectangle pourra référencer un objet de type Rectangle1, ou Rectangle2, ou plus

généralement de n’importe quelle classe qui est un sous-type de Rectangle.

On se rapproche de la définition française, une interface vue comme la couche limite entre deuxéléments par laquelle ont lieu des échanges et des interactions. Ici, l’interface va être la zone de contactentre le bout de code utilisé et le code qui l’utilise, le bout de code devenant interchangeable. Au lieud’utiliser des références de type Rectangle1 et de devoir tout remplacer par Rectangle2  si ondécide de changer de classe, nous utiliserons des références de type Rectangle qui pourront tout aussi

 bien désigner des objets de type Rectangle1 que Rectangle2.

Considérons par exemple la classe Carre. Nous pourrions vouloir tester si un certain carré est plusgrand, en termes de surface, qu’un rectangle. Sans interface nous nous appuierions sur une classe avec parexemple Rectangle1 au lieu de Rectangle dans le code ci-dessous. Mais la méthodeplusGrand  ne serait utilisable qu’avec des instances de Rectangle1. Si nous voudrions pouvoirégalement comparer avec des instances de Rectangle2 nous devrions surcharger la méthodeplusGrand en rajoutant une méthode identique mais qui cette fois prend une instance de Rectangle2en paramètre. A quoi bon dupliquer le code puisqu’il est le même ? Et si je décide d’utiliser une troisièmemodélisation des rectangles il va me falloir surcharger à nouveau la méthode plusGrand. En précisantRectangle nous venons d’écrire du  code  polymorphe  (et donc faire du polymorphisme) c'est-à-diredu code qui accepte des objets de différents types. Le code fonctionne pour tous les sous-types deRectangle.

Exemple  public class Carre {

 private Point basGauche;

 private double cote;… public double getLargeur() {

return this.cote;} public double getHauteur() {

return this.cote;} public double aire() {

return this.getLargeur()*this.getHauteur();} public  boolean plusGrand(Rectangle r){

return this.aire()>r.aire();}…

} Dans nos diagrammes de classes nous représenterons les interfaces de la même façon que les classes

mais avec la mention « interface » au dessus du nom et le lien « C implémente I » sera symbolisé par uneflèche en pointillé dont l’extrémité est un triangle dirigé vers l’interface.

Interface

Rectangle

+ double getLargeur()+ double getHauteur()+ double getBordGauche()+ double getBordDroit()+ double aire()+ boolean dans(Rectangle r)

 

Rectangle1

- Point basGauche- Point hautDroit

+ Rectangle1(double gauche,double  droit, double  bas,double  haut)

+ double getLargeur()+ double getHauteur()+ double getBordGauche()+ double getBordDroit()+ double aire()+ boolean dans(Rectangle r)

Rectangle2

- Point basGauche- double largeur, hauteur

+ Rectangle2(double  gauche,double  droit, double  bas,double  haut)

+ double getLargeur()+ double getHauteur()+ double getBordGauche()+ double getBordDroit()+ double aire()+ boolean dans(Rectangle  r)

Page 89: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 89/199

Les  concepts de programmation  Programmation Les interfaces  [email protected] – B227 

87 

3.26.2.  Des contrats

 Nous avons vu qu’une classe C qui précise implémenter une interface I se doit de fournir un code àtoutes les méthodes dont les entêtes sont listées dans I. C peut avoir d’autres méthodes additionnelles,mais elle doit comporter au moins toutes les méthodes indiquées dans I. Les interfaces peuvent donc

également être vues comme des contrats, des obligations auxquelles s’engagent les classes déclarant lesimplémenter.

Cela constitue un bon moyen de se répartir le travail au sein d’une équipe. Face à un projet, l’équipe seréunie pour modéliser le problème en définissant un certain nombre d’interfaces. Chaque membre peutensuite implémenter un certain nombre de ces interfaces sans attendre le code des autres car il connaît lesentêtes des méthodes qu’ils se sont engagés à implémenter.

3.26.3.  Des propriétés

Les interfaces peuvent être utilisées pour représenter un TDA, mais elles peuvent aussi exprimer des propriétés qu’ont les types. De très nombres interfaces fournies avec Java sont de ce type.

Sur notre exemple, la méthode plusGrand prend en paramètre un Rectangle, mais on pourrait bien sûr vouloir comparer un carré avec un autre carré. Là encore, nous pourrions surcharger la méthodeen rajoutant une méthode plusGrand qui prendrait cette fois un Carre en paramètre. Le code seraitidentique. Nous pourrions vouloir comparer notre Carre avec un Triangle ou un Cercle. Mais ilserait laborieux et sujet à erreurs de dupliquer à nouveau le code. En fait, dans la méthode plusGrand,tout ce qui nous importe c’est que le paramètre dispose d’une méthode aire(). Les autres méthodes deRectangle  sont inutiles pour plusGrand. On voudrait pouvoir dire que plusGrand  fonctionne

 pour tout paramètre « qui possède une aire ».

Il suffit pour cela de déclarer une interface PossedeAire  qui ne mentionne que la méthodeaire()  et mentionner PossedeAire  pour type du paramètre de plusGrand. Si Rectangle,Carre, Triangle  et Cercle  déclarent implémenter l’interface PossedeAire, nous pourronscomparer des carrés avec des objets de toutes ces classes en ayant écrit une seule méthode plusGrand.

Exemple  public interface Rectangle {

 public double getLargeur(); public double getHauteur(); public double getBordGauche(); public double getBordDroit(); public double aire(); public  boolean dans(Rectangle r);

}

 public interface PossedeAire { public double aire();

}

 public class Rectangle1 implements Rectangle, PossedeAire{

}

 public class Carre {… public  boolean plusGrand(PossedeAire o){

return this.aire()>o.aire();}…

}

 Notez qu’une classe peut implémenter plusieurs interfaces  comme dans l’exemple ci-dessus oùRectangle1 implémente à la fois Rectangle et PossedeAire.

Page 90: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 90/199

 

88 

Les  concepts de programmation  Programmation Les interfaces  [email protected] – B227 

3.26.4.  Type dynamique et liaison tardive

Le polymorphisme est rendu possible grâce à un mécanisme dit de liaison tardive. Regardezl’exemple ci-dessous. Les classes Rectangle1  et Cercle1  implémentent toutes deux l’interfacePossedeAire. La procédure principale de Test déclare une référence pa de type possedeAire et

initialise cette référence avec l’adresse d’un rectangle ou d’un cercle en fonction de la saisie del’utilisateur. Quel code sera exécuté lors de l’appel à pa.aire() ?

On voit ici qu’il est impossible de savoir lors de la compilation quel objet désignera pa. On distinguedeux types pour les références. Le type statique qui correspond à la déclaration, ici possedeAire pourpa. Et le  type dynamique qui correspond au type de l’objet référencé, lequel peut évoluer au cours del’exécution. Vu que le type dynamique ne peut pas être connu lors de la compilation, le compilateur ne se

 base que sur le type statique pour le mécanisme de résolution, c'est-à-dire pour déterminer à quoicorrespondent les éléments précisés dans le code. Pour l’appel à pa.aire(), le compilateur ne trouve

 pas d’erreur vu qu’une méthode aire() existe forcément pour pa, l’interface possedeAire obligeantles classes qui l’implémentent à posséder une telle méthode. Le compilateur mémorise de plus qu’arrivé àce stade du code, la méthode qui sera appelée aura double aire()  pour signature. Mais ce n’est qu’àl’exécution que la détermination du code à exécuté sera effectuée, d’où le qualificatif de tardif. Larecherche du code s’effectuera à partir du type dynamique. En supposant que l’utilisateur saisissent « 1 »,le type dynamique de pa sera Rectangle1 et c’est donc dans cette classe qu’on recherchera le code dedouble aire().

Pour résumer, la détermination de la signature de la méthode qui sera recherchée s’effectue en tenantcompte des types statiques des références, mais la recherche du code à exécuté n’a lieu qu’au moment del’exécution et la recherche débute dans le type dynamique de l’objet receveur.

Exemple  public interface PossedeAire { public double aire();

}

 public class Rectangle1 implements Rectangle, PossedeAire{…

 public double aire() {return this.getLargeur()*this.getHauteur() ;

}}

 public class Cercle1 implements PossedeAire{…

 public double aire() {return Math.PI*this.getRayon()*this.getRayon();

}}

 public class Test { public static final void main(String[]args) {

System.out.println("Indiquez 1 pour un rectangle (une autre "+"valeur pour un cercle)") ;

int saisie = Clavier.lireInt() ;PossedeAire pa ;if (saisie==1) {

pa = new Rectangle1(0.0, 10.0, 0.0, 5.0) ;}else {

pa = new Cercle1( new Point(0.0,0.0), 1.0);}System.out.println("L’aire est de "+pa.aire()) ;

}

}

Page 91: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 91/199

Les  concepts de programmation  Programmation Les interfaces  [email protected] – B227 

89 

 Nous pourrions être tentés d’écrire systématiquement des interfaces pour tous les concepts que nousintroduisons mais les interfaces ne sont pas toujours utiles. Leur intérêt réside principalement dans le

 polymorphisme qu’elles autorisent et cet intérêt est grandement réduit s’il n’existe qu’une seule classeimplémentant l’interface. Nous n’écrirons donc pas systématiquement des interfaces pour toutes lesclasses de nos programmes.

Résumé-  Une interface est constituée exclusivement d’un ensemble d’entêtes de méthodes (donc pas de

variables d’instances, pas de constructeurs et pas de code pour les méthodes).-  On ne peut pas créer d’instance d’une interface. Pas de new I() si I est une interface.-  Une interface peut correspondre à la déclaration d’un type de données abstrait, vu uniquement au

travers de ses méthodes, ou correspondre à une propriété en termes de services fournis.-  Une classe C peut déclarer implémenter une interface I en précisant « implements I » dans sa

déclaration. Elle est alors contrainte de fournir une implémentation pour chaque entête précisédans l’interface, et C est un sous-type de I.

-  si A est un sous-type de B, alors une expression de type A est aussi de type B. Par conséquent, une

référence de type I peut référencer n’importe quel objet d’une classe implémentant I. Ce principe permet d’écrire du  code polymorphe, c'est-à-dire du code pouvant être utilisé pour différentstypes.

-  Une classe peut implémenter plusieurs interfaces.-  Le type statique d’une référence correspond à celui de sa déclaration.-  Le type dynamique correspond au type de l’objet référencé.-  Lors de l’appel d’une méthode, c’est le compilateur qui détermine l’entête correspondant à l’appel

en se basant exclusivement sur les types statiques.-  Ce n’est qu’à l’exécution que le code à exécuter est recherché : on recherche dans la classe du type

dynamique l’entête déterminée à la compilation.

Page 92: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 92/199

 

90 

Les  concepts de programmation  Programmation L’héritage  [email protected] – B227 

3.27.  L’héritage

 Nous sommes accoutumés à décrire des concepts par spécialisation. Les mammifères sont desanimaux. Des animaux particuliers car caractérisés par la présence de mamelles, d’un cœur à quatre

cavités, d’un système nerveux et encéphalique développé, par une température interne constante et unerespiration de type pulmonaire. Les ruminants sont des mammifères. Des mammifères particulierscaractérisés par le fait qu’ils sont herbivores et que leur digestion s’accompagne d’un processus deremastiquassions de l’alimentation après ingestion. On peut décrire la vache comme un ruminant

 particulier, cela évite de devoir repréciser pour la vache tout ce qui est déjà connu pour les ruminants etde ne s’attarder que sur les spécificités de la vache. L’héritage est un mécanisme analogue qui permet dedécrire une classe comme étant une spécialisation d’une autre, évitant ainsi les redites qui comme nous lesavons sont source de problèmes en informatique.

Si on a le code d’une classe on pourrait se dire que ça ne prend pas de temps d’en faire un copier-coller puis de compléter pour en faire une spécialisation. Mais si on s’aperçoit qu’il y a des points àmodifier dans la classe de base, il faudra aussi les répercuter dans la classe spécialisée avec le risqued’oublier une mise à jour. Et de toute façon à quoi bon avoir le code en double ? Qui plus est, nousn’avons pas toujours le code source. Prenons l’exemple d’une fenêtre graphique. Java fournit la classeJFrame qui modélise une telle fenêtre, mais une fenêtre vide. Je ne connais pas le code de cette classe, et

 je ne suis vraiment pas enthousiaste à l’idée de réaliser un code similaire (En suis-je capable de toutefaçon ?). Peu importe en fait car on n’a pas besoin de disposer du code source pour pouvoir étendre cetteclasse. Je peux décrire ma fenêtre comme étant l’extension d’une JFrame à laquelle j’ajoute un texte etun bouton. Pour décrire ma fenêtre je n’ai plus qu’à préciser ce que j’ajoute par rapport à la fenêtre vide.Et si d’aventure Java fournit une implémentation plus performante de JFrame  j’en bénéficieautomatiquement, ce qui n’aurait pas été le cas avec une copie du code source.

Prenons un exemple plus proche de ce que nous avons déjà fait. Un point de l’espace n’est rien d’autrequ’un point du plan avec une troisième coordonnée (sa cote). C’est un point particulier, qui a un état pluscomplet et des services additionnels. Dans l’exemple ci-dessous on définit Point3D par extension dePoint via la mention « extends Point ». On dit alors que Point3D  hérite de Point. Point estla classe mère ou super-classe, et Point3D est la classe fille ou sous-classe.

Exemple  public class Point { private double abscisse ; private double ordonnee ;

 public Point(double x, double y){this.abscisse = x ;this.ordonnee = y ;

} public double getAbscisse() {

return this.abscisse ;

} public double getOrdonnee() {return this.ordonnee ;

} public String toString() {

return "("+this.getAbcisse()+", "+this.getOrdonnee()+")";

} public  boolean equals(Object o) {

if (o instanceof Point) {Point p = (Point)o;return this.getAbscisse()==p.getAbscisse()

  && this.getOrdonnee()==p.getOrdonnee();}else {return false;

}

}…} 

 public class Point3D extends Point { private double cote;

 public Point3D(double x, double y, double z){super(x, y);this.cote = z;

}

 public double getCote() {return this.cote;

}

 public String toString() {return "("+this.getAbcisse()+", "+this.getOrdonnee()+", "+this.getCote ()+")";

}

 public  boolean equals(Object o) {if (o instanceof Point3D) {Point p = (Point3D)o;return super.equals(o)

&& this.getCote()==p.getCote();}else {return false;

}

}} 

Page 93: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 93/199

Les  concepts de programmation  Programmation L’héritage  [email protected] – B227

 

91 

Point3D hérite de l’état et des méthodes de Point. La mention « extends Point » fait qu’unPoint3D a une abscisse, une ordonnée, un accesseur getAbscisse, … et ce sans qu’on n’ait rien de

 plus à préciser. On se contente de décrire les spécificités du Point3D  par rapport au Point  encomplétant l’état et/ou le comportement.

Le principe d’encapsulation demeure. Chaque classe est responsable des variables d’instance qu’elledéfinit, et ces dernières sont private. Le constructeur de Point3D doit initialiser tout son état, maisl’abscisse et l’ordonnée ont été déclarées dans la super-classe et leur initialisation doit donc être déléguéeau constructeur de Point. On retrouve donc un chaînage de constructeurs mais il ne s’agit plus d’appelerun constructeur de la même classe, mais de la super-classe d’où le super(…) au lieu d’un this(…).D’une manière générale, le constructeur d’une classe-fille commence par un appel à un constructeurde la super-classe  (super(args)) pour initialiser la partie héritée de l’état, puis il initialise

directement les éventuelles variables additionnelles déclarées. Si la première ligne du constructeurd’une classe fille ne commence pas par super(args), alors Java insère implicitement l’appelsuper().

Une classe fille peut bien sûr avoir des méthodes additionnelles à celles héritées comme ici getCote.Une classe fille peut redéfinir une méthode héritée. On parle de  redéfinition  lorsqu’une classe fille

définit une méthode portant le même nom et les mêmes paramètres qu’une méthode héritée. C’est le casici pour toString. Si Point3D  ne redéfinissait pas cette méthode, un appel à toString  sur unPoint3D conduirait à l’appel de la méthode toString héritée. Mais la chaîne retournée ne serait pasadéquate pour un point de l’espace car la cote n’y serait pas précisée.

La sous-classe peut évidemment faire appel à ses méthodes héritées. Notez par exemple que danstoString on fait à appel à this.getAbscisse() et this.getOrdonne().

Le lien d’héritage est un lien de sous-typage. La classe fille est un sous-type de la classe mère. UnObjet de type Point3D est aussi de type Point. Dès lors, une référence de type Point peut référencer

une instance de Point3D. Les mécanismes de résolution et de liaison tardive demeurent inchangés. Lasignature des méthodes à invoquer est déterminée à la compilation à partir des types statiques, et larecherche du code à exécuter est effectuée à l’exécution en commençant la recherche dans la classe dutype dynamique. Regardons ce que cela donne avec la procédure main ci-dessous.

Exemple … public static void  main(String[] arg) {

Point pt = new Point3D( 2.5, 1.5);System.out.println( pt.toString() );System.out.println( pt.getAbscisse() );

}} 

Lors de l’appel à pt.toString() on recherche le code d’une méthode toString() à partir dutype dynamique de pt, donc à partir de la classe Point3D. Vu qu’il existe une méthode toString() dans Point3D c’est ce code qui est appelé (si il n’y en avait pas eu, la recherche se serait poursuiviedans la classe-mère, et si il n’y en avait pas eu dans Point on serait allé voir dans la classe mère dePoint (comment ça Point n’a pas de classe mère ? Mais si ! On y vient, vous allez voir que Point aune classe mère). Le code de toString() de Point3D fait un appel à this.getAbcisse(), onrecherche donc une méthode getAbscisse() dans le type dynamique de this  (Point3D) mais iln’y en n’a pas donc la recherche se poursuit dans la classe mère, Point, et on trouve le code degetAbscisse() qui devra être exécuté. Il en va ainsi lors de l’appel à pt.getAbscisse() dansmain, une méthode getAbscisse()  est recherchée dans Point3D  et comme il n’y en n’a pas la

recherche se poursuit dans Point et c’est au final le code de la méthode getAbscisse() de Point qui est exécuté. On voit ici qu’avec une recherche qui remonte de classe-mère en classe-mère jusqu’àtrouver la signature recherchée, la redéfinition d’une méthode masque la méthode héritée

Page 94: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 94/199

 

92 

Les  concepts de programmation  Programmation L’héritage  [email protected] – B227 

Au sein d’une classe fille, l’appel à une méthode héritée se fait sur this, sauf si on est en train

de redéfinir la méthode héritée auquel cas l’appel s’effectue sur super. Regardez la redéfinition dela méthode equals. Un appel à this.equals au lieu de super.equals conduirait à effectuer unappel récursif de la méthode equals  de Point3D. En précisant super.equals  le mécanisme de

liaison tardive va débuter la recherche du code de la méthode equals non pas dans Point3D mais danssa super classe et c’est donc bien la méthode equals de Point qu’on invoque.

Il n’y a pas d’héritage multiple en Java. Une classe ne peut avoir qu’une seule classe mère. Mais laclasse mère peut elle-même avoir une classe mère. De plus, deux classes-filles peuvent avoir la mêmemère. Les liens d’héritage forment donc des arborescences, ou plutôt UN arbre car il y a une racinecommune : si une classe ne déclare pas explicitement étendre une classe mère, elle étend par défaut

la classe Object. Voilà pourquoi Point a une classe mère bien qu’elle ne précise pas explicitementétendre qui que ce soit. Vous comprenez à présent pourquoi toute classe a par défaut une méthodeequals et une méthode toString. Toute classe hérite directement ou indirectement de Object etdonc tout classe hérite des méthodes toString et equals de Object.

Dans les diagrammes de classes le lien d’héritage se traduit par une flèche pleine dont l’extrémité estun triangle désignant la classe mère. On omet généralement la classe Object  qui demeure implicite.Voici un schéma correspondant à quelques extensions possibles de Point.

Le premier intérêt de l’héritage que nous avons soulevé concerne la capacité qu’il procure à déclarerune classe par extension d’une autre, factorisant ainsi les méthodes partagées au sein de la classe mère

 plutôt que de devoir dupliquer le code. Mais l’héritage induisant un lien de sous-typage nous retrouvonségalement des possibilités de polymorphisme, comme nous avons pu en voir avec les interfaces. Si uneméthode prend en paramètre un Point, nous pourrons lui fournir en paramètre un Point  ou unPoint3D ou un Point3DColore ou encore un PointEtiquette.

Si une classe fille déclare une variable qui porte le même nom qu’une variable dont elle hérite, il y amasquage de la variable héritée. Si par exemple Point3D  déclarait une variable abscisse, toute

Point- double abscisse- double ordonnee+ Point(double x, double y)+ double getAbscisse()+ double getOrdonnee()+ boolean equals(Object o)+ String toString()+ boolean dans(Rectangle r)

+ double distance(Point p)

Point3D

- double cote

+ Point3D(double x,double y, double z)

+ double getCote()+ boolean equals(Object o)+ String toString()

PointEtiquette

- String etiquette

+ PointEtiquette(double x,double y, String etiquette)

+ String getEtiquette()+ String toString()

Point3DColore

- Color couleur

+ Point3DColore(double x,

double y, double z,Color couleur)

+ Color getCouleur()+ boolean equals(Object o)+ void dessiner(Graphics g)

Page 95: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 95/199

Les  concepts de programmation  Programmation L’héritage  [email protected] – B227

 

93 

instance de Point3D aurait deux variables abscisse: celle héritée de Point, et celle introduite dansPoint3D. Mentionner this.abscisse dans Point3D ferait référence à la variable introduite dansPoint3D. Pour accéder à la variable héritée il faudrait préciser super.abscisse. C’est

généralement une très mauvaise idée que de déclarer une variable portant le même nom qu’unevariable héritée et je vous recommande donc de ne pas le faire .

Enfin, il est possible de spécifier protected  pour visibilité, symbolisé par le caractère # dans lesdiagrammes de classes. Une variable protected  est accessible dans la classe où elle est définie maisaussi dans toutes ses sous-classes. C’est donc un niveau de visibilité intermédiaire. Très rares sontcependant les situations où il est judicieux d’utiliser le niveau protected  et nous continuerons donc dedéclarer private  nos variables d’instance (Les sous-classes les initialiseront via un appel àsuper(agrs) et pourront y accéder indirectement via les méthodes publiques).

Résumé-  Une classe B déclare étendre une classe A via la mention « extends A ».

-  Si B étend A alors B  hérite (de l’état et du comportement) de A. On dit alors que B est la classe fille (ou sous-classe) et A la classe mère (ou super-classe).

-  Le constructeur d’une classe-fille commence par un appel à un constructeur de la super-classe(super(args)) pour initialiser la partie héritée de l’état, puis il initialise directement leséventuelles variables additionnelles déclarées.

-  Au sein d’une classe fille, l’appel à une méthode héritée se fait sur this, sauf si on est en train deredéfinir la méthode héritée auquel cas l’appel s’effectue sur super.

-  Une classe fille est un sous-type de sa classe mère.-  En Java il n’y a pas d’héritage multiple : une classe ne peut déclarer qu’une seule mère (qui elle-

même peut avoir une mère, …). Si une classe ne précise pas de classe mère, elle hérite par défautde la classe Object. Les liens d’héritage forment donc un arbre ayant Object  pour racine.

Toute classe hérite directement ou indirectement de Object.-  Une classe fille peut redéfinir une méthode héritée. On parle de redéfinition lorsqu’une classe filledéfinit une méthode portant le même nom et les mêmes paramètres qu’une méthode héritée. Cela

 permet de préciser un autre comportement que celui hérité.-  Le premier intérêt de l’héritage est la capacité qu’il procure à déclarer une classe par extension

d’une autre, factorisant ainsi les méthodes partagées au sein de la classe mère plutôt que de devoirdupliquer le code. Mais l’héritage induisant un lien de sous-typage nous retrouvons également des

 possibilités de polymorphisme, comme nous avons pu en voir avec les interfaces.-  Les méthodes d’une classe fille peuvent accéder directement aux variables d’instances déclarées public ou protected  dans la classe mère. L’accès ne peut être qu’indirect si la visibilité est private.

-  Le code qui sera exécuté lors de l’invocation d’une méthode n’est déterminé qu’à l’exécution(liaison tardive) par une recherche qui commence dans la classe du type dynamique et qui remontede classe-mère en classe-mère jusqu’à trouver l’entête identifiée à la compilation.

Page 96: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 96/199

 

94 

Les  concepts de programmation  Programmation L’héritage  [email protected] – B227 

Page 97: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 97/199

Complexité  Programmation Complexité temporelle d’un algorithme  [email protected] – B227 

95 

4. Complexité

Déterminer la complexité d’un algorithme vise à donner une estimation de son efficacité. Les notionsde temps de calcul et de mémoire nécessaire à la représentation des données sont primordiales puisqu’un

 programme doit non seulement retourner le résultat souhaité pour toutes les valeurs possibles en entrée,mais également retourner le résultat dans un temps « raisonnable » pour l’utilisateur en utilisant unequantité « raisonnable » de mémoire. Il est toutefois difficile, à la simple vue de l’algorithme, de juger dutemps ou de la mémoire qui seront effectivement nécessaires pour obtenir le résultat. Cela dépend en effetà la fois de la taille des données (par exemple, rechercher un mot dans un dictionnaire dépend du nombrede mots qui figurent dans ce dictionnaire) et de l’ordinateur sur lequel sera utilisé le programme. Nousallons nous dégager de la dépendance vis-à-vis de l’ordinateur utilisé et évaluer la complexité d’unalgorithme en fonction uniquement de la taille des données.

L’ambition est ici de vous sensibiliser à cette notion importante et de vous donner les bases. À l’issuede ce chapitre vous devriez être capable de calculer la complexité d’algorithmes relativement simples etdonc de comparer des algorithmes en termes de complexité. Le cours de structures algorithmiques que

vous aurez par la suite développera davantage votre aptitude en la matière.

4.1.  Complexité temporelle d’un algorithme

On ne peut pas exprimer l’efficacité temporelle d’un algorithme à partir de chronométrages d’uneimplémentation de cet algorithme sur une machine donnée. En effet, on peut difficilement donner lestemps de calcul pour toutes les données possibles, et de plus, ces temps n’évoqueront pas grand chose àquelqu’un ne disposant pas de la même machine. Nous devons faire abstraction de la machine utilisée.Fournir la complexité d’un algorithme va consister à donner une mesure reflétant « la quantité de calcul »nécessaire pour aboutir au résultat en fonction de la taille de la donnée et indépendamment du matériel.

Une opération à coût unitaire est une opération qui requiert un temps qui ne dépend pas de la tailledes données. Par exemple, « ajouter 1 » ou vérifier l’égalité de deux entiers sont des opérations à coûtunitaire, contrairement au produit de matrices car le temps requis dépend de la taille des matrices. Voiciune liste non exhaustive d’opérations à coût unitaire :

-  Appel d’un algorithme (Attention ! l’appel est à coût unitaire, mais l’algorithme appelé peut, lui,ne pas être à coût unitaire),

-  Déclaration d’une variable,-  Affectation d’une variable,-  Toutes les opérations prédéfinies sur les Booléens, les entiers, les flottants, les caractères et les

chaînes de caractères (cf. mémento),-  Toutes les primitives prédéfinies,-  …

DéfinitionLa  complexité temporelle  d’un algorithme est la quantité d’opérations à coût unitaire utiles pourmener à terme la tache, cette quantité étant exprimée en fonction de la taille des données. 

Supposons que nous voulions estimer la complexité de la fonction suivante qui étant donné un entierborne retourne la somme 1+2+3+4+…+(borne-1)+borne.

Exemple  public static int sommeDepuis1( int borne ) {

int somme=0;for (int i=1; i<=borne; i++) {

somme = somme + i;}

return somme;}

Page 98: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 98/199

 

96 

Complexité  Programmation Complexité temporelle d’un algorithme  [email protected] – B227 

Le test d’infériorité, les déclarations de somme et i, les affectations et la somme (somme+i) sont desopérations à coût unitaire. Six opérations à coût unitaire sont effectuées dans tous les cas : les déclarationsde i et somme, leurs initialisations, le test et le return. Ensuite, le nombre de pas de boucle effectuéscorrespond à la valeur de borne, chaque pas réclamant quatre opérations à coût unitaire (le test

 permettant de savoir si on a atteint borne, une addition, une affectation, l’incrémentation de i). Cettefonction réclame donc 6+(borne*4)4 opérations à coût unitaire.

 Notez que cet algorithme est particulièrement inefficace puisque 1+2+3+…+borne= (borne*(

borne+1)/2)  et qu’il est donc possible d’écrire un algorithme ne requérant que 4 opérations à coûtunitaire quelle que soit la valeur de borne (un addition, un multiplication, une division et un return).

Pour certains algorithmes la complexité peut varier grandement d’une instance de données à l’autre,même à taille de données identique. C’est pourquoi on distingue trois analyses de complexité :

-  La complexité dans le  pire des cas : pour chaque taille de données t, on détermine le coût sur ladonnée de taille t la plus coûteuse.

-  La complexité dans le  meilleur cas  : on détermine cette fois le coût sur la donnée la moins

coûteuse.-  La complexité en moyenne : pour chaque taille de données t, on détermine la moyenne des coûtssur l’ensemble des données ayant t pour taille.

Regardons l’exemple de la fonction indexPremiereOccurrence.

Exemple  public static int indexPremiereOccurrence(int[] tab, int x){// Entrée : tab, un tableau d’entiers, et un entier x.

// Sortie : Retourne l’index de la première occurrence de x dans tab si

// x figure dans tab, et retourne -1 sinon.

int index=0;while (index<tab.length && tab[index]!=x)) {

index++;}if (index==tab.length) {

return -1;}else {

return index;}

}

Cet algorithme réalise une déclaration, une affectation, puis 45 opérations à coût unitaire (deux tests,une conjonction et une incrémentation) par pas de boucle effectué puis de 1 à 3 opérations lors de la sortiede la boucle, et enfin un test et une instruction return. Le nombre d’opérations nécessaires dépend donc

étroitement du nombre de pas de boucle réalisés.  Dans le meilleur cas, c’est-à-dire celui qui demande le moins d’opérations, le premier élément du

tableau est x. Dans ce cas, il n’y aura aucun pas de boucle et le test de la conditionnelle sera négatif. 7opérations à coût unitaire sont nécessaires, et ce quelle que soit la longueur du tableau. La complexité entemps dans le meilleur des cas est dite en temps constant puisque le nombre d’opérations à réaliser nevarie pas en fonction de la taille de la donnée.

4 Nous verrons que le calcul précis du nombre d’opérations à coût unitaires requis par l’algorithme n’est pas très intéressant et que nous nous

limiterons à borner la complexité à des facteurs constants près

 si vous comptez quelques opérations à coût unitaire de plus ou de moins cen’est pas grave. 5 Comme nous le verrons, l’important n’est pas de déterminer précisément le nombre d’instructions mais d’estimer comment ce nombre varie enfonction de la taille de la donnée.

Page 99: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 99/199

Complexité  Programmation Complexité spatiale d’un algorithme  [email protected] – B227 

97 

  Dans le pire des cas, c’est-à-dire celui qui demande le plus d’opérations, tab  ne comporteaucune occurrence de x. Toutes les cases du tableau devront être consultées avant de s’apercevoirqu’aucune des cases ne contient la valeur x. Il y aura tab.length pas de boucle et un total de 2+(5*tab.length)+1+2  opérations réalisées. La complexité temporelle dans le pire des cas est diteslinéaire en la taille de la donnée, dans le sens où le nombre d’opérations à réaliser varie linéairement enfonction de la taille de la donnée (nous y reviendrons).

  La complexité en moyenne est plus délicate à déterminer car il faut connaître des informations surles données manipulées. Par exemple, si on sait que cet algorithme est toujours appelé avec des tableauxcomportant une unique occurrence de l’entier recherché mais qu’il y a équiprobabilité entre les cases d’ytrouver l’entier, alors on effectue en moyenne tab.length  /2  pas de boucle.5+(5*tab.length/2) opérations sont donc réalisées en moyenne et la complexité en moyenne estdonc elle aussi linéaire en la taille de la donnée.

4.2.  Complexité spatiale d’un algorithme

Définition

La complexité spatiale d’un algorithme est l’espace mémoire nécessaire pour mener à terme la tache.Cette quantité est également fonction de la taille des données et on distingue comme pour lacomplexité temporelle les trois cas d’analyse : le pire cas, le meilleur cas et en moyenne. 

Les espaces mémoire nécessaires pour la représentation d’un entier, d’un caractère, d’un booléen oud’un nombre à virgule flottante sont considérés comme unitaires. Il s’agit dès lors de déterminer commentvarie la taille de l’espace occupé par les différentes variables en fonction de la taille des données.

Cette information est toute aussi importante que la complexité en temps puisque les ressources en

mémoire sont limitées dans un ordinateur.

4.3.  Comportement asymptotique

4.3.1.  Définitions et notations

Déterminer la complexité d’un algorithme vise à donner une estimation de son efficacité. Ce qui est particulièrement intéressant, c’est de voir comment évolue la complexité en fonction de la taille desdonnées, et en particulier, de voir le comportement sur des données de grande taille car dans ce cas seull’ordre de grandeur de la complexité devient pertinent. En d’autres termes, on regarde comment s’accroîtla complexité en fonction de la taille des données à la limite, s’affranchissant ainsi des données de petites

tailles. La complexité va donc être évaluée en termes d’efficacité asymptotique.

Définition

f(n)  est dans O(g(n))  si et seulement si il existe deux constantes positives K  et n0  telles que|f(n)|K|g(n)| pour tout nn0. (cf. Fig. 1 (a). On dit aussi que f(n) est de l’ordre de O(g(n)) ou que f(n) est en O(g(n))). 

En d’autres termes, les fonctions figurant dans O(g(n)) sont les fonctions qui au-delà d’une certainevaleur n0 demeurent inférieures à g(n) à un facteur positif près. On retrouve ici l’idée de ne regarder lecomportement qu’asymptotiquement (on ne considère pas les valeurs de n  inférieures à n0) et des’abstraire de la rapidité de la machine (les mesures sont à un facteur positif près). Pour l’algorithmeindexPremiereOccurrence que nous avons pris pour exemple, la taille de la donnée, c’est à dire le

nombre de cases unitaires nécessaires à la représentation des données, est de 1+tab.length (le tableaucomporte tab.length  entiers et un second paramètre entier est passé). La fonction donnant la

Page 100: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 100/199

 

98 

Complexité  Programmation Comportement asymptotique  [email protected] – B227 

complexité dans le pire des cas de l’algorithme est 5+(5*tab.length), c’est à dire f(n)=(5*(n)), où n est la taille de la donnée. Nous pouvons donc dire que la complexité temporelle de cet algorithme est enO(n) où n  est la taille de la donnée (il suffit de prendre K=5 et n0=3 pour s’en convaincre). On ditégalement que sa complexité est linéaire car elle varie de façon linéaire vis-à-vis de la taille des données.

Fig. 1 Illustrations des définitions des notations asymptotiques O (a),   (b)6 et   (c)9 .

Remarque

D’après la définition de la notation O, une complexité en O(n) est également une complexité en O(n 2),et plus généralement en O(g(n)) où g(n)  est une fonction supérieure à n. Toutefois, lors de ladétermination de la complexité on recherche la fonction minimale  qui est asymptotiquement une

 borne supérieure à un facteur positif près de la complexité. 

Cette notation introduit des classes de complexité. Les principales d’entre elles sont :-  les algorithmes en temps constant (O(1) : la complexité ne dépend pas de la taille de la donnée),

- les algorithmes logarithmiques (O(

log(n))),

-  les algorithmes linéaires (O(n)),-  les algorithmes quadratiques (O(n2)),-  les algorithmes cubiques (O(n3))-  les algorithmes exponentiels (O(2n), O(10n),…) 

Pour mieux se rendre compte des ordres de grandeurs, voici le temps que mettrait un ordinateurcapable d’effectuer un million d’opérations par seconde pour réaliser f(n) opérations :

f(n) n=16 n =256 n =1.024 n =1.048.576

1 1 s 1 s 1 s 1 slog(n) 4 s 8 s 10 s 20 s

n 16 s 256 s 1,02 ms 1,05 secn2  256 s 65,5 ms 1,05 sec 1,8 semainesn3  4,1 ms 16,8 ms 17,9 min 36,5 ans2n  65,5 ms 3,71063 ans 5,710294 ans 2,110315639 ans

Important

Pour déterminer l’ordre de complexité dans le pire cas, il est souvent inutile de déterminer précisémentle nombre d’opérations à coût unitaire requises.  Il suffit de borner supérieurement unesurestimation de ce nombre à un facteur près.

6 Définition page suivante. 

K |g(n)|

| f(n)

n0 

(a) 

K |g(n)|

| f(n)|

n0 

(b) 

k 1|g(n)|

| f(n)|

n0 

(c) 

K 2|g(n)|

Page 101: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 101/199

Complexité  Programmation Comportement asymptotique  [email protected] – B227 

99 

De manière similaire à la notation O  qui permet de donner une borne supérieure du comportementasymptotique à un facteur près, nous introduisons   pour donner une borne inférieure.

Définition

f(n)  est dans (g(n))  si et seulement si il existe deux constantes positives K  et n0  telles que

|f(n)|K|g(n)| pour tout nn0. (cf. Fig. 1 (b)). Enfin, le comportement asymptotique peut parfois être borné à un facteur près à la fois inférieurement

et supérieurement par une même fonction :

Définition

f(n) est dans (g(n)) si et seulement si f(n) est à la fois dans O(g(n)) et dans (g(n)), c’est-à-dire s’ilexiste trois constantes positives K1, K2 et n0 telles que k1|g(n)| f(n)K2|g(n)| nn0. (cf. Fig. 1(c)). 

4.3.2.  Règles de simplification

Elimination 

de 

 facteurs 

constants 

Théorème

O(Cf(n)) = O(f(n)) pour toute constante C>0. 

Démonstration

  O(Cf(n))O(f(n)) : soit une fonction h(n)O(Cf(n)). Par définition, il existe K  et n0  tels que|h(n)|K|Cf(n)|  pour tout n n0. Par conséquent, n n0, |h(n)|K2|f(n)|  avec K2=KC, et donch(n)O(f(n)).

  O(f(n))O(Cf(n)) :soit une fonction h(n) O(f(n)). Par définition, il existe K  et n0  tels que|h(n)|K|f(n)|  pour tout n n0. Par conséquent, n n0, |h(n)|K2|Cf(n)|  avec K2=K/C, et donc

h(n)O(Cf(n)).Important

Il est possible d’éliminer les facteurs constants dans l’expression d’une classe de complexité. 

Exemple 

O(30230n3)=O(n3) et on préférera désigner cette classe de complexité par O(n3). 

Elimination des termes de  poids  faible 

Théorème

O(|f(n)|+|g(n)|) = O(max(|f(n)|, |g(n)|)) 

Démonstration

 O(|f(n)|+|g(n)|)  O(max(|f(n)|, |g(n)|)) : Soit h(n) une fonction de O(|f(n)|+|g(n)|). Par définition,il existe K  et n0  tels que nn0, |h(n)|K(|f(n)|+|g(n)|). Puisque n |f(n)|+|g(n)|  2|max(|f(n)|,

|g(n)|)| on a nn0 |h(n)|K2|max(|f(n)|,|g(n)|)|  avec K2=2K et donc h(n)O(max(|f(n)|, |g(n)|)).  O(|f(n)|+|g(n)|)   O(max(|f(n)|, |g(n)|)) : Soit h(n)  une fonction de O(max(|f(n)|, |g(n)|)). Par

définition, il existe K  et n0  tels que nn0, |h(n)|K|max(|f(n)|, |g(n)|)|. Puisque n |max(|f(n)|,|g(n)|)||f(n)|+|g(n)|, on a nn0 |h(n)|K(|f(n)|+|g(n)|) et donc h(n)O(|f(n)|+|g(n)|).

Important

Il est possible d’éliminer les termes de poids faible dans l’expression d’une classe de complexité. 

Exemple O(20n3+2n2+24n)=O(20n3)=O(n3) et on préférera désigner cette classe de complexité par O(n3). 

Page 102: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 102/199

 

100 

Complexité  Programmation Comportement asymptotique  [email protected] – B227 

Complexité  d’une  séquence 

Théorème

Soit une séquence <bloc1>;<bloc2>. Si la complexité de <bloc1> est en O(f(n)) et que celle de<bloc2> est en O(g(n)) alors la complexité de la séquence est en O(f(n)+g(n)). 

Complexité  d’une conditionnelle  simple 

Théorème

Soit la conditionnelle if (<condition>) <blocSi> else <blocSinon>. Si la complexitéde <condition> est en O(f(n)), que celle de blocSi est en O(g(n)) et que celle de blocSinon en O(h(n)), alors la complexité de la conditionnelle est en O(f(n)+max(g(n), h(n))). Dans le cas

 particulier d’une condition en O(1), la complexité de l’alternative est donc en O(max(g(n), h(n))). 

En pratique, ce théorème nous permet d’ignorer la partie de l’alternative qui est la moins coûteuse et

de se focaliser uniquement sur l’expression (condition, blocSi  ou blocSinon) qui demande le plus de temps.Exemple 

if (x<0) {procedure367DuCours(x) ;

}else {

y = 0;}

La condition étant un simple test et l’expression correspondant au cas où la condition n’est pasrespectée étant une simple affectation, la complexité de cette conditionnelle correspond à celle de

procedure367DuCours.

Complexité  d’une boucle 

Théorème

Si la complexité du corps d’une boucle est en O(f(n)), que la condition est en O(1) et que le nombre de pas de boucle effectués est en O(g(n)), alors la complexité de la boucle est en O(f(n)*g(n)). 

Exemple  public static int indexPremiereOccurrence(int[] tab, int x){// Entrée : tab, un tableau d’entiers, et un entier x.

// Sortie : Retourne l’index de la première occurrence de x dans tab si

// x figure dans tab, et retourne -1 sinon.int index=0;while (index<tab.length && tab[index]!=x)) {

index++;}if (index==tab.length) {

return -1;}else {

return index;}

}

Le corps de la boucle while est en temps constant et au plus tab.length pas de boucle aurontlieu. La complexité de la boucle est donc en O(tab.length*1)=O(tab.length).

Page 103: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 103/199

Complexité  Programmation Comportement asymptotique  [email protected] – B227 

101 

Exemple  public static int sommeMatrice(int[][] mat){// Entrée : mat, une matrice d’entiers

// Sortie : Retourne la somme de tous les éléments de mat.

int somme=0;

for (int ligne=0; ligne<mat.length; ligne++) {for (int colonne=0; colonne<mat[ligne].length; colonne++) {

somme = somme + mat[ligne][colonne];}

}return somme;

}

Le corps de la boucle for  la plus interne (portant sur colonne) demande une addition et uneaffectation. Ce corps est donc en O(1), et comme mat[ligne].length  pas de cette boucle serontréalisés, la complexité dans le pire cas de cette boucle est en O(mat[ligne].length). La boucle la

 plus externe (celle portant sur ligne) a pour corps une boucle de complexité en

O(mat[ligne].length), et mat.length  pas de cette boucle seront réalisés. Si mat  est unematrice rectangulaire de l  lignes par c  colonnes, alors la complexité de cette fonction est en O(l*c)(donc linéaire en la taille de la matrice).

Remarque

Attention ! Il peut arriver que les règles de simplification ne donnent qu’une surestimation grossière dela complexité et il faut parfois faire une étude plus fine pour déterminer une meilleure borne. 

Exemple if (tab.length<0) {

indexVal=indexPremiereOccurrence(tab, val);}else {

System.out.println(“Taille positive”);}

On pourrait croire que la complexité de cette conditionnelle est celle deindexPremiereOccurrence si on utilise la règle de simplification de l’alternative puisqu’à la foisla condition et le « bloc sinon » sont en temps constant. Cependant, un tableau ne peut pas être de taillenégative et tab.length  est donc supérieur ou égal à 0. Par conséquent, il n’y aura jamais d’appel àindexPremiereOccurrence et la complexité de la conditionnelle est en O(1). Remarquons que cecode pourrait être clairement simplifié en remplaçant toute la conditionnelle par le bloc sinon (puisque le

 bloc sinon sera systématiquement exécuté), et que l’auteur de cette conditionnelle devrait se recycler.Exemple 

if (prixTTC<0.00000001) {

traitementPrixTresTresBas(prixTTC) ; }else {

listeDesVentes[nombreDArticles]=prixTTC;nombreDArticles++ ; 

}

Ce cas se distingue du cas précédent par le fait que la condition peut éventuellement être vérifiée.Toutefois, si on a l’assurance qu’en pratique cette condition n’est jamais vérifiée sur l’ensemble desdonnées que le programme aura à traiter, on se ramène au cas précédent et la complexité de laconditionnelle est en O(1). Cette fois ci le programmeur n’est pas forcément farfelu : partant du principe« qui peut le plus, peut le moins », il a peut-être écrit un programme très général qui est valable y comprissur des cas extrêmes mais qui est employé actuellement sur des données où un tel cas ne survient jamais.

Le développeur pourrait par contre adapter son code pour l’utilisation actuelle qui en est faite ensupprimant le traitement spécifique de ce cas improbable.

Page 104: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 104/199

 

102 

Complexité  Programmation Comportement asymptotique  [email protected] – B227 

Exemple for (int i=-1 ; i<leTableau.length ; i++) {

if (i==-1) {somme = factorielle(m);

}else {

somme = somme + leTableau[i];}

}

Si la complexité de l’algorithme factorielle(m)  retournant la factorielle de m  est en O(m), on pourrait conclure hâtivement que la complexité de la conditionnelle est en O(m) et que la complexité de la boucle est en O(n*m) (où n est la taille du tableau leTableau), chacun étant en O(m)). Cependant,l’appel à factorielle n’a lieu que dans un seul des pas de la boucle, et tous les autres pas sont en O(1).L’ensemble des pas pour lesquels i  vaut de 0 à leTableau.length-1   réclament de l’ordre deO(leTableau.length) opérations, et le cas où i vaut –1 réclame un temps en O(leTableau.length).La complexité de la boucle est donc en O(m+leTableau.length). Si ce code est correct d’un point de

vue résultat, sa lisibilité aurait pu être plus grande en sortant de la boucle le cas (i==-1) : faire apparaîtrel’appel à factorielle dans la boucle peut faire croire que plusieurs appels à factorielle auront lieu.Le code ci-dessous est donc beaucoup plus clair et sa complexité est bien plus évidente.

Somme = factorielle(m);for (int i=0 ; i<leTableau.length ; i++) {

somme = somme + leTableau[i];}

Exercice PR023 p.  173  Corrigé p. 176 

Page 105: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 105/199

Quelques stratégies  Programmation Algorithmes itératifs et invariants de boucle  [email protected] – B227 

103 

5.  Quelques stratégies

Trouver l’idée d’un algorithme est le point qui peut sembler le plus difficile. Ne pas y parvenir lors des premiers exercices peut conduire à baisser les bras et à se dire qu’on ne doit pas être fait pour la

conception d’algorithmes. Il ne faut pourtant pas être un génie ou un savant fou pour trouver une idéed’algorithme adaptée à une tâche. C’est tout simplement une aptitude qui réclame de la pratique. Plusvous étudierez d’algorithmes, plus l’écriture d’algorithmes sera naturelle chez vous. Non pas parce quevous aurez mémorisé bêtement une quantité considérable d’exemples, mais parce que vous aurezextrapolé les stratégies communes entre ces algorithmes.

Hélas, le temps consacré à ce cours est bien trop faible pour faire un tour exhaustif des grandesfamilles d’algorithmes. Nous n’en verrons que quelques unes, en espérant que votre intérêt et votrecuriosité vous conduiront à en étudier d’autres par vous même en dehors de ce cours.

5.1.  Algorithmes itératifs et invariants de boucle

La plupart des algorithmes que nous avons vus jusqu’ici sont itératifs. Ils impliquent une ou plusieurs boucles afin d’itérer des actions jusqu’à aboutir au résultat souhaité.

Les compétences que nous aimerions avoir concernent (1) l’élaboration d’un algorithme, (2) la preuveque cet algorithme rend un résultat dans tous les cas, et (3) la preuve que le résultat obtenu est toujourscelui attendu. Nous avons déjà abordé les invariants de boucle comme une solution pour apporter ces

 preuves, et nous avons spécifié que trouver les invariants n’est pas une tâche à réaliser après l’élaborationde l’algorithme mais avant ou parallèlement. Soit, mais c’est bien plus facile à dire qu’à faire.

S’appuyer sur des invariants n’est pas naturel. Si on demande à une personne de dire en langagenaturel comment il tri un tas de feuilles numérotées, il commence généralement par une phrase du type :«je compare la première et la seconde, si la seconde doit aller avant la première je fais passer la seconde

en premier, puis je compare la première et la troisième, … ». On a tendance, et c’est bien naturel, àdécomposer notre tâche comme une suite d’actions. 

L’ennui, c’est que comme nous l’avons vu notre code est de taille fixe alors que nos données sont detaille variable. On peut donner la séquence pour trier 3 feuilles, 4 feuilles, 100 feuilles, mais pourgénéraliser à un nombre quelconque de feuilles nous devons utiliser des boucles. Il ne nous faut dès lorsplus raisonner en termes de séquence d’actions, mais en termes de situation. Par exemple, si masituation est d’avoir déjà trié n  feuilles, alors l’itération à réaliser est d’insérer la (n+1)ème  feuille à sa

 place dans le paquet trié. Je me retrouve alors avec (n+1) feuilles triées. Et si j’itère jusqu’à ce que toutesmes feuilles soient dans le tas, toutes mes feuilles seront ordonnées.

Parvenir à raisonner en terme de situation vous sera utile non seulement pour les algorithmes itératifs,mais aussi pour d’autres stratégies comme la programmation par récurrence. C’est donc un bon

investissement !

5.1.1.  Le principe

Le schéma d’un algorithme itératif est extrêmement simple :

while (<pasFini>) {<faire un pas> 

}

Ce qu’on espère c’est qu’à l’issue de cette boucle nous parvenons au résultat attendu. Considérons lecas d’un algorithme modifiant les données en mémoire (on pourrait généraliser à des algorithmeseffectuant des entrées sorties en ne considérant pas uniquement l’état de la mémoire mais également l’étatdes périphériques).

Page 106: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 106/199

 

104 

Quelques stratégies  Programmation Algorithmes itératifs et invariants de boucle  [email protected] – B227 

while (<pasFini>) {<faire un pas> 

}

La transition va se faire par un certain nombre d’itérations, faisant passer l’état de la mémoire pardifférentes étapes.

Pour que nous soyons assurés d’aboutir au bon résultat, plusieurs conditions doivent être remplies. La première, c’est que chaque pas doit nous rapprocher du résultat. Dans notre exemple des feuilles àtrier, nous devons aboutir à ce que toutes les feuilles soient bien ordonnées. Il y a fort à parier que dansune étape intermédiaire un certain nombre de feuilles soient déjà triées et qu’un certain nombre ne lesoient pas encore. Un pas peut alors consister à prendre l’une des feuilles non classées et à l’insérerconvenablement parmi les feuilles triées. A l’issue d’un pas on est plus proche du résultat puisqu’il y adavantage de feuilles triées.

Mais cette première condition ne suffit pas. En effet, la validité du pas s’appuie sur des hypothèses surla situation. Dans notre exemple, on se base sur le fait que l’ensemble des feuilles déjà considérées estconvenablement trié. Si d’aventure au début d’un pas le tas de feuille déjà traitées est dans le désordre,l’insertion d’une feuille supplémentaire n’arrangera rien à la situation et ce quel que soit l’endroit où onl’insère. Si on n’a pas avant le pas un paquet trié on n’a aucune chance de parvenir au résultat. Cettecondition de validité de la situation est notre invariant ! C’est la condition garantissant qu’on est sur lavoie menant au résultat. Dans notre cas l’invariant est « avant le pas i il y a (i-1) feuilles triées ». Notrealgorithme doit rester sur la bonne voie et il doit donc vérifier cet invariant.

Rester sur la bonne voie sous entend qu’initialement nous y sommes. Avant même le premier pas deboucle les conditions de validité doivent être vérifiées. Dans notre cas, rien n’est à faire : avant le

 premier pas de boucle il faut qu’il y ait 0 feuille de triées, et trier 0 feuilles consiste à ne rien faire. Il faut

ensuite que chaque pas de boucle nous laisse dans un état valide . Chaque pas de boucle doit maintenirl’invariant. Dans notre exemple, nous avons (i-1) feuilles de triées avant le pas i et il en faut i de triéesaprès ce pas. Notre pas doit par conséquent faire en sorte qu’une feuille de plus soit triée en insérant parexemple au bon endroit une feuille non classée dans la pile triée. Partant d’un état valide et chaque pasnous laissant dans un état valide, nous sommes assurés de rester dans des états valides. C’est le principed’induction7  qui nous l’assure. Comme de plus chaque pas nous rapproche du résultat nous sommesassurés d’y parvenir au bout d’un certain nombre de pas.

7 ( S(0)  (i, S(i)S(i+1) )   i S(i)) 

État initial de la mémoire 

État final de la mémoire comportant le résultat 

État initial de la mémoire 

État final de la mémoire 

État de la mémoire après le pas 1 

État de la mémoire après le pas 2 

État de la mémoire après le pas 3 

1er pas

2 me pas

3 me pas

4 me pas

dernier pas…

 

Page 107: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 107/199

Quelques stratégies  Programmation Algorithmes itératifs et invariants de boucle  [email protected] – B227 

105 

Toutefois, parvenir au résultat après un certain nombre de pas n’est pas satisfaisant si ce « certainnombre » est infini. Il faut donc définir une condition d’arrêt pour notre boucle qui sera forcémentvérifiée après un nombre fini de pas.

Récapitulons. Pour que nous soyons surs d’obtenir le bon résultat au bout d’un temps fini il faut :

1  Considérer le résultat à obtenir et imaginer une situation intermédiaire.

2  Imaginer une étape qui puisse nous faire passer d’une situation intermédiaire à une autre plus proche du résultat.

3  Exhiber l’invariant, c’est à dire les conditions à vérifier pour être sur la voie menant à lasolution. Une situation sera valide dès lors qu’elle vérifie cet invariant.

4  Faire en sorte qu’avant la boucle nous soyons dans un état valide.

5  Vérifier que tout pas de boucle nous amène à un état valide si la situation avant le pas est ellemême valide.

6  Vérifier que la condition d’arrêt caractérisant l’obtention du résultat sera toujours atteinteaprès un nombre fini de pas.

 Notons que les étapes 2 et 3 sont simultanées. L’invariant « apparaît » en même temps que l’idée du pas puisque ce dernier fait des hypothèses (l’invariant !) sur la situation courante.

5.1.2.  Quelques types classiques d’invariants

a – On considère une  partie de  plus en  plus  grande de l’entrée 

 Notre entrée est constituée de n éléments (ou de n parties). La solution pour un petit nombre

(potentiellement nul) de parties est triviale (dans le sens où son obtention ne nécessite aucune itération).On considère qu’on a calculé la solution pour i éléments et un pas de boucle nous conduit à l’obtention dela solution pour i+1 éléments de l’entrée. On ne se préoccupe pas des éléments non encore traités de ladonnée : on considère que notre entrée est constituée uniquement des (i+1) premiers éléments et on tentede trouver la solution sachant que nous disposons de celle pour les i premiers. On a terminé quand tousles éléments de l’entrée ont été pris en considération.

 Exemple : Le tri par insertion

Entrée

Solution pour une donnéelimitée aux i premiers éléments

i éléments

Avant le pas de boucle

Après le pas de boucle

Solution pour une donnée limitée aux (i+1)premiers éléments

8 3 33 7 40 14 2 11 19 6 22 13 5 17 9 10 18 32 16 65

2 3 7 8 14 33 40

2 3 7 8 11 14 33 40

Page 108: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 108/199

 

106 

Quelques stratégies  Programmation Algorithmes itératifs et invariants de boucle  [email protected] – B227 

 Nous avons pris le tri d’un paquet de feuilles numérotées pour exemple tout au long de la présentationde la méthode, ce qui est totalement équivalent au tri d’un tableau d’entiers. Ecrivons à présent le coderéalisant cette tâche.

Un état intermédiaire entre un tableau complètement désordonné et un tableau trié par ordre croissant,est un tableau dont les premiers (ou les derniers) éléments sont triés. Plus il y aura d’éléments triés, plusnous serons proche de la solution. Si on suppose que les i premiers éléments sont triés, un pas devraitnous amener à un état ou au moins les (i+1) premiers éléments sont bien triés. On peut y parvenir eninsérant le (i+1)ème  entier à sa place (dans l’ordre croissant) parmi les i premiers. Notre condition devalidité est que les i premiers éléments soient triés. Ce qui nous donne le pas de boucle de la pagesuivante.

Exemple incomplet  public static void  triParInsertion(int[] entiers) {

<initialisation nous plaçant dans un état valide>int i = 1;int pos, vali ;while (<tous les entiers ne sont pas triés>) {

// On insère l’entier d’index i parmi les (i-1) premiers éléments

// qui sont déjà dans un ordre croissant

pos=i ;vali=entiers[i] ;while ((pos>0) && (entiers[pos-1]>vali)) {

entiers[pos]= entiers[pos-1] ;pos-- ;

}entiers[pos]=vali ;i++ ;

}}

Le ième pas de boucle insère l’entier d’index i parmi les i premiers entiers du tableau. Pour que nousrestions sur la voie menant à la solution, il faut que « avant le i ème pas de boucle, les i premiers entiers dutableau sont triés pas ordre croissant ». Avant le premier pas de boucle, le premier entier doit être trié.

 Nous n’avons donc rien à faire de plus avant la boucle pour nous mettre sur la bonne voie.

Il nous reste à déterminer la condition d’arrêt. Nous allons devoir classer tour à tour les élémentsd’index 1, 2, 3, etc. jusqu’à l’index (entiers.length-1). Une boucle for  est donc bien plusindiquée qu’une boucle while puisque nous connaissons précisément tous les pas à effectuer et il n’y a

 pas lieu d’interrompre la boucle avant d’avoir effectué tous ces pas.

Exemple 

 public static void  triParInsertion(int[] entiers) {int pos, vali ;for (int i=1 ; i<entiers.length ; i++) {

// On insère l’entier d’index i parmi les (i-1) premiers éléments

// qui sont déjà dans un ordre croissant

pos=i ;vali=entiers[i] ;while ((pos>0) && (entiers[pos-1]>vali)) {

entiers[pos]= entiers[pos-1] ;pos-- ;

}entiers[pos]=vali ;

}}

Page 109: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 109/199

Quelques stratégies  Programmation Algorithmes itératifs et invariants de boucle  [email protected] – B227 

107 

b – On  produit  une  part  de  plus en  plus  grande de la  sortie 

 Notre sortie est constituée de n éléments (ou de n parties). On considère qu’on a déjà calculé les i  premiers éléments de notre sortie et un pas de boucle nous conduit à l’obtention de la (i+1)ème partie. Ona terminé quand toutes les parties de la sortie ont été produites.

 Exemple : Le tri par sélection

Dans un état intermédiaire du tri par insertion, les i premiers éléments du tableau sont dans un ordrecroissant. Nous pourrions envisager une condition plus forte : que les i  premiers éléments du tableausoient dans un ordre croissant ET que ces i  premiers éléments soient les i  plus petits éléments dutableau. Ce qui revient à dire qu’on a déjà mis à leur place définitive les i plus petits éléments du tableau.

Le ième pas de boucle va donc devoir mettre à sa place définitive (en ième position) le ième plus petitélément du tableau. Si on considère qu’avant ce pas de boucle les (i-1) plus petits éléments on été mis à

leur place (de l’index 0 à l’index i-2), le ième plus petit élément est forcément le plus petit des élémentsd’index supérieur ou égal à i-1. Le pas de boucle va donc rechercher le plus petit élément parmi ceuxd’index compris dans [i-1, entiers.length] et  placer  cet élément à l’index i-1. A l’issue de ce  pasde  boucle, notre invariant sera respecté  puisque nous aurons les i  plus  petits éléments à leur   place définitive.

Exemple incomplet  public static void  triParSelection(int[] entiers) {

<initialisation nous plaçant dans un état valide>int i = 0;int pos, vali, plusPetit ;while (<tous les entiers ne sont pas triés>) {// Les (i-1) plus petits éléments du tableau ont été placés à leur

// place définitive entre l’index 0 et l’index (i-2). On va// rechercher le plus petit élément parmi ceux d’index compris dans

// [i, tailleTab] et le placer à la position i.

plusPetit=i ;for (int pos=i+1 ; pos<entiers.length ; pos++) {

if (entiers[pos]<entiers[plusPetit]) {

plusPetit= 

pos ;}

}vali=entiers[i] ; // on a trouvé le plus petit, 

entiers[i] entiers[plusPetit]; // on échange sa place avec 

entiers[plusPetit] vali ; // l’entier d’index i 

i++;}}

Entrée

i premiers éléments de la solution

Avant le pas de boucle

Après le pas de boucle

(i+1) premiers éléments de la solution

8 3 33 7 40 14 2 11 19 6 22 13 5 17 9 10 18 32 16 65

2 3 5 6 7 8 9

2 3 5 6 7 8 9 10

Page 110: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 110/199

 

108 

Quelques stratégies  Programmation Algorithmes itératifs et invariants de boucle  [email protected] – B227 

Avant le premier pas de boucle, 0 éléments doivent être mis à leur place définitive. Nous n’avons doncrien à faire pour nous placer dans un état valide.

Il nous reste à considérer les pas de boucle à effectuer et quand interrompre la boucle. Si les(entiers.length-1) plus petits éléments ont été mis à leur place en début de tableau, le seul élémentrestant, celui dans la case d’index entiers.length-1  est forcément le plus grand de tous. Parconséquent, le tableau est entièrement trié après avoir placé chacun des entiers.length-1  plus

 petits éléments. Là encore une boucle for s’impose.

Exemple public static void  triParSelection(int[] entiers) {

int pos, vali, plusPetit ;for (int i=0 ; i<entiers.length-1 ; i++) {

plusPetit=i ;for (int pos=i+1 ; pos<entiers.length ; pos++) {

if (entiers[pos]<entiers[plusPetit]) {

plusPetit= pos ;}

}vali=entiers[i] ; // on a trouvé le plus petit, 

entiers[i] entiers[plusPetit]; // on échange sa place avec 

entiers[plusPetit] 

vali ; // l’entier d’index i i++;

}}

c  – On réduit  l’espace de recherche 

On doit rechercher un élément dans un ensemble. Si l’ensemble est désordonné, il y a fort à parier

qu’il faudra adopter une approche considérant une partie de plus en plus grande de la donnée. Par contre,si un ordre est connu sur l’ensemble il peut être utilisé pour éviter de considérer inutilement certainséléments.

Après chaque pas de boucle, la taille du sous-ensemble pouvant contenir l’élément est réduit. Ons’arrête quand on a trouvé l’élément, ou quand la taille du sous-ensemble est nulle ou réduite à un élément.

 Exemple : La recherche dichotomique

EntréeAvant le pas de boucle

Après le pas de boucle

Sous-ensemble où peut figurer l’élément recherché

2 3 5 6 7 8 9 10 11 13 14 16 17 18 19 22 32 33 40 65 12

2 3 5 6 7 8 9 10 11 13 12

Sous-ensemble où peut figurer l’élément recherché

8 9 10 11 13 12

Page 111: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 111/199

Quelques stratégies  Programmation Algorithmes itératifs et invariants de boucle  [email protected] – B227 

109 

 Notre tâche est de vérifier l’existence d’un entier dans un ensemble ordonné d’éléments. Nous allonsillustrer cette tâche par le cas particulier de la recherche d’un entier dans un tableau d’entiers trié de façoncroissante.

Initialement, l’entier recherché peut être dans n’importe quelle case du tableau. Nous comptonsréduire l’ensemble des cases où il peut se trouver jusqu’à (a) soit trouver la case où il se trouve, (b) soits’apercevoir qu’il n’y figure pas. Une étape intermédiaire serait donc de se retrouver à chercher l’entierdans un sous-ensemble de notre tableau, trié lui aussi. Notre pas doit réduire davantage encore l’espacedes possibilités. Les éléments de notre tableau étant ordonnés, si un élément du tableau est plus petit quel’élément recherché, on sait que tous les éléments d’index inférieurs sont encore plus petits ; si l’élémentrecherché figure dans le tableau, il ne peut être situé qu’à un index supérieur. Si au contraire l’élément tirédu tableau est plus grand que l’élément recherché, aucune des cases d’index supérieur ne peut contenirl’élément recherché.

Si on compare systématiquement l’élément recherché au plus petit des entiers de notre tableau, nousobtenons la technique prenant en compte une partie de plus en plus grande de la donnée ; on va parcourirun à un les entiers de notre tableau jusqu’à trouver l’élément recherché, ou s’apercevoir qu’il ne figure

 pas dans le tableau (atteint la fin du tableau ou un élément plus grand que l’élément recherché). Chaque

 pas de boucle réduirait notre ensemble des possibilités d’une case.Si on compare l’entier recherché avec l’entier situé au milieu du tableau, c’est la moitié des

 possibilités qu’on écarte avec le test. On n’est pas obligé de prendre l’élément situé au milieu pourconverger vers la solution, la condition nécessaire pour nous garantir la validité est de n’avoir excluaucune case où pourrait apparaître l’élément recherché. Le fait de comparer avec le premier élément,l’élément du milieu ou encore un élément d’index tiré au hasard, n’influe que sur la rapidité de laconvergence vers la solution.

On peut rapprocher cette méthode du jeu où l’on doit deviner un prix après quelques propositions. Achaque suggestion d’un prix, on sait si le prix recherché est supérieur ou inférieur ce qui nous permetd’exclure des possibilités et donc de réduire la fourchette dans laquelle se situe le prix à trouver. Le

 joueur proposant 1, puis 2, puis 3, ... convergera bien moins vite que celui essayant systématiquement le

 prix situé en milieu de fourchette, mais tous deux sont assurés de trouver le prix.On peut s’arrêter dès que l’espace des possibilités a été réduit à une seule case puisque le test de présence devient alors trivial.

D’un point de vue complexité, puisque la taille de l’espace de recherche est divisée par deux à chaque pas de boucle, si on note n la taille initiale de la donnée on fera au plus log2(n) pas de boucle et lacomplexité dans le pire des cas est en O(log2(n)).

Exemple public static boolean present(int[] entiers, int entierRecherche) {

int borneGauche, milieu, bornedroite ;

// Initialement toutes les cases peuvent contenir l’entier recherché

borneGauche=0 ;

borneDroite= entiers.length-1 ;while (borneGauche<borneDroite) {// Après chaque pas de boucle, la// taille de l’ensemble des cases pouvant contenir l’entier recherché a// été réduit de moitié

milieu (borneGauche+borneDroite)/2 ;

if (entiers[milieu]<entierRecherche) {borneGauche=milieu+1;

}else {

borneDroit=milieu ;}

}return (entiers[borneGauche]==entierRecherche);

}

Page 112: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 112/199

 

110 

Quelques stratégies  Programmation Algorithmes récursifs et l’approche « Diviser pour régner »  [email protected] – B227 

5.2.  Algorithmes récursifs et l’approche « Diviser pour régner »

Comme nous le verrons, l’approche « diviser pour régner » ne s’applique pas uniquement auxalgorithmes récursifs. Toutefois, cette technique et la récursivité sont abordées dans le même chapitre carles algorithmes utilisant l’approche « diviser pour régner » sont dans leur très grande majorité récursifs.

5.2.1.  La récursivité

a – Définition et   principe 

DéfinitionUn algorithme est récursif  s’il fait appel à lui-même. 

Un algorithme qui fait appel à lui même c’est suspect. Ca fait penser à un serpent qui se mord laqueue, à un processus sans fin. On peut bien sûr facilement écrire des algorithmes infinis comme nousavons tout aussi facilement écrit des boucles dont on ne sort jamais. L’algorithme ci-dessous par exempleest la transcription de l’idée que (n!==n!) ; il est bien évident que dire « pour réaliser la tâche il faut

réaliser la tâche » est un discourt aussi trivial qu’inutile. L’algorithme ci-dessous provoque une sérieinfinie d’appel et ne retourne jamais le moindre résultat.Exemple ERRONE !!!  public static entier factorielle(int n) {

return factorielle(n) ;}

Important

Un sous-programme peut faire appel à lui-même, mais JAMAIS avec les mêmes entrées (sinon on neconverge pas). 

Un algorithme ne s’appelle pas pour le simple plaisir d’être récursif. Si un algorithme est récursifc’est parce qu’il s’appuie sur le principe d’induction :

Si on sait réaliser la tâche pour de petites tailles (sans appel récursif)et Si on sait résoudre une tâche à partir des solutions de tâches équivalentes de plus petites taillesalors On sait résoudre la tâche quelle que soit sa taille

Ce principe est très largement utilisé en mathématique dans les preuves par induction (ou récurrence). Nous l’avons utilisé pour les algorithmes itératifs et leurs invariants et comme avec ces algorithmes desconditions de validité doivent être vérifiées pour être assuré d’aboutir au résultat souhaité.

La première condition du principe d’induction n’est pas sans rappeler l’initialisation à un état valideavant la boucle que nous avons vu dans la section précédente. Pour des données de petite taille nousdevons être capables de fournir le résultat sans même un appel récursif (respectivement, sans même uneitération dans la section précédente).

La seconde condition se rapproche davantage du pas de la boucle dans la section précédente. Onsuppose qu’on est en milieu de traitement et que des résultats sur des sous-tâches sont connus pourfournir le résultat de la tâche.

Le schéma d’un algorithme récursif ressemble bien souvent au schéma ci-dessous :

 public static <type retour> algoRecursif(<instance>){if (<instance si petite qu’on a une solution sans même un appel récursif>){

return <solution triviale de l’instance> ;}else {

s1  algoRecursif(<instance plus petite 1>) ;…si  algoRecursif(<instance plus petite i>) ;

return combinaison(s1, s2, …, si) ;}

1

Page 113: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 113/199

Quelques stratégies  Programmation Algorithmes récursifs et l’approche « Diviser pour régner »  [email protected] – B227 

111 

On trouve bien évidemment de grandes similarités entre la méthode d’écriture d’algorithmes itératifset celle d’écriture d’algorithmes récursifs ci-dessous :

1  Considérer que nous sommes capables de résoudre toute tâche similaire de plus petite taille.

2  Imaginer une étape qui combine les résultats sur des instances de plus petites tailles pour obtenirla solution.

3  Ecrire le code permettant d’obtenir la solution sans appel récursif des instances de petites tailles.

4  Vérifier qu’on dispose de la solution pour suffisamment d’instances de petites tailles et que toutappel récursif peut être résolu par combinaison de résultats des instances de petites taillestraitées.

Important

Tout appel récursif doit directement ou indirectement se ramener à un/des cas « simple(s) »(solvable(s) sans appel récursif). 

b – Les appels récursifs  sur  un exemple 

Les algorithmes récursifs n’introduisent aucun élément nouveau. Vous connaissez tous les conceptsnécessaires. Néanmoins, l’enchaînement des appels est souvent déroutant dans les premiers temps. Riende tel par conséquent que de dérouler l’exécution de l’appel à une fonction récursive pas à pas pour mieuxcomprendre comment le principe d’induction permet d’obtenir le résultat.

La définition de la fonction factorielle en mathématique est récursive. C’est pourquoi elle est trèssouvent utilisée comme exemple :

0 ! = 1n != n * ((n-1) !) si n>0

Le code récursif pour cette fonction découle immédiatement de cette définition mathématique : on peut calculer la valeur de n! pour peu qu’on connaisse la valeur de (n-1)! et que la factorielle de 0 soitconnue. Le cas trivial 0! suffit puisqu’on se ramène systématiquement à la factorielle du précédent :factorielle de 1 se déduira directement de factorielle de 0, factorielle de 2 va être déduit de factorielle de 1laquelle se déduit de factorielle de 0, et plus généralement factorielle de n va indirectement se déduire defactoriel de 0.

 public static entier factorielle(int n) {

if (n==0) {return 1 ;

}else {

return n * factorielle(n-1);}

}

Que se passe-t’il si on fait appel à factorielle(3) ? Exactement ce qui se passe dans tout appeld’algorithme. Une variable est créée pour chaque paramètre formel (n  ici), avec la fonctionfactorielle pour portée (n n’existera plus dès qu’on sortira de la fonction) et la valeur du paramètreeffectif pour valeur (3 ici).

n3

Page 114: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 114/199

 

112 

Quelques stratégies  Programmation Algorithmes récursifs et l’approche « Diviser pour régner »  [email protected] – B227 

Le code est ensuite évalué. n n’étant pas nul, on doit retourner le résultat de (3*factorielle(2)).Pour cela, il faut d’abord déterminer la valeur de factorielle(2) : un appel récursif est donc réalisé.L’exécution de factorielle(3) est momentanément suspendue : on reviendra précisément à l’endroitoù on en était dès qu’on aura le résultat de factorielle(2).

L’appel factorielle(2) va créer une variable pour le paramètre formel (n’ pour ne pas se mêlerles pinceaux), lui affecter la valeur du paramètre effectif ((n-1) soit 2) puis exécuter le code defactorielle.

factorielle(3)

n’  n’étant pas nulle, l’appel à factorielle(2)  va retourner la valeur de(2*factorielle(1)). Là encore, nous ne pouvons pas retourner la valeur immédiatement puisquecela demande le résultat de l’appel à factorielle(1). L’exécution de factorielle(2) est doncsuspendue et elle reprendra précisément où on en était dès qu’on aura le résultat de l’appel àfactorielle(1).

factorielle(3)

L’appel à factorielle(1) crée bien évidemment une variable pour le paramètre formel (n’’) etsa valeur n’étant pas nul, c’est la valeur de (1*factorielle(0)) qui doit être retournée. L’exécution

de factorielle(1) est donc suspendue jusqu’à l’obtention de la valeur de factorielle(0).

 public static int factorielle( int n ) {if (n==0) {

return 1;}else {

return n * factorielle(n-1) ;}} 

n

 public static int factorielle( int n’ ) {

if (n’==0) {return 1;}else {

return n’ * factorielle(n’-1) ;}} 

 public static int factorielle( int n ) {if (n==0) {

return 1;}else {

return n * factorielle(n-1) ;}}   public static int factorielle( int n’ ) {

if (n’==0) {return 1;

}else {

return n’ * factorielle(n’-1) ;}} 

 public static int factorielle( int n’’ ) {if (n’’==0) {

return 1;}else {

return n’’ * factorielle(n’’-1) ;}} 

3

n’ 2

n 3

n’ 2

n’’ 1

Page 115: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 115/199

Quelques stratégies  Programmation Algorithmes récursifs et l’approche « Diviser pour régner »  [email protected] – B227 

113 

factorielle(3)

Lors de l’appel factorielle(0), le paramètre étant nul, nous connaissons immédiatement lerésultat à retourner : 1. C’est en effet le cas trivial que nous avons identifié pour lequel nous savonsrépondre sans même un appel récursif. L’appel à factorielle(0) retourne donc la valeur 1.

factorielle(3)

L’exécution de factorielle(1) peut donc reprendre où nous l’avions laissée puisqu’à présent lavaleur de factorielle(0) est connue et on peut donc retourner 1*factorielle(0) (soit 1).

 public static int factorielle( int n ) {if (n==0) {

return 1;}else {

return n * factorielle(n-1) ;}} 

 public static int factorielle( int n’ ) {if (n’==0) {

return 1;}else {

return n’ * factorielle(n’-1) ;}} 

 public static int factorielle( int n’’ ) {if (n’’==0) {

return 1;}else {

return n’’ * factorielle(n’’-1) ;

}} 

 public static int factorielle( int n’’’ ) {if (n’’’==0) {

return 1;}else {

return n’’’ * factorielle(n’’’-1) ;}

 public static int factorielle( int n ) {if (n==0) {

return 1;}else {

return n * factorielle(n-1) ;}} 

 public static int factorielle( int n’ ) {if (n’==0) {

return 1;}

else {return n’ * factorielle(n’-1) ;}} 

 public static int factorielle( int n’’ ) {if (n’’==0) {

return 1;}else {

return n’’ * factorielle(n’’-1) ;}} 

1

n 3

n’ 2

n’’ 1

n’’’ 0

n 3

n’ 2

n’’ 1

Page 116: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 116/199

 

114 

Quelques stratégies  Programmation Algorithmes récursifs et l’approche « Diviser pour régner »  [email protected] – B227 

factorielle(3)

L’exécution de factorielle(2) reprend alors et retourne 2*factorielle(1) soit 2.factorielle(3)

Enfin, l’exécution de factorielle(3)  reprend puisque la valeur de factorielle(2)  est à présent connue. La valeur 3*factorielle(2) (soit 6) est dès lors retournée.

factorielle(3)

Sur cet exemple on peut voir que la fonction s’appelle toujours sur des instances plus faciles et ce jusqu’à tomber sur l’un des cas triviaux (ici il n’y en avait qu’un : 0!). Puis, le résultat sur les instancestriviales permet d’obtenir le résultat de l’appel précédent, qui lui même permet de calculer le résultat del’appel précédent, et de proche en proche on parvient à obtenir le résultat du tout premier appel.

 public static int factorielle( int n ) {if (n==0) {

return 1;

}else {

return n * factorielle(n-1) ;}

 public static int factorielle( int n’ ) {if (n’==0) {

return 1;}else {

return n’ * factorielle(n’-1) ;}} 

 public static int factorielle( int n ) {if (n==0) {

return 1;}else {

return n * factorielle(n-1) ;}

1

2

6

n 3

n’ 2

n 3

Page 117: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 117/199

Quelques stratégies  Programmation Algorithmes récursifs et l’approche « Diviser pour régner »  [email protected] – B227 

115 

c  – Un autre exemple d’algorithme récursif  : le tri   par  insertion 

 Nous avons vu que le chemin menant à un algorithme itératif n’est pas si différent de celui menant àun algorithme récursif. On peut d’ailleurs trouver un algorithme itératif et un algorithme récursif pour une

même tâche. A titre d’exemple, écrivons la version récursive du tri par insertion.

Dans un premier temps, nous considérons que nous avons à trier un tableau tab de taille entierset nous supposons que nous savons trier tout tableau plus petit. Il nous faut ensuite concevoir le moyen de

 parvenir à trier nos taille entiers en s’appuyant sur la possibilité de s’appeler sur des tableaux plus petits. Supposons que nous ayons fait un appel récursif pour trier les (taille-1) premier éléments dutableau. Pour obtenir le tri des taille  premiers éléments il ne reste plus alors qu’à insérer letailleième élément au bon endroit.

 Nous tenons notre cas général : nous savons comment nous ramener à des cas plus petits. Il nous resteà fournir la solution pour des cas triviaux en nous assurant que ces derniers suffiront pour déterminer lessolutions pour tous les cas. Le tri d’un tableau ne contenant aucun élément est aussi immédiat que le trid’un tableau comportant un seul élément : il suffit de ne rien faire !

Est-ce que ces cas triviaux suffisent ? Oui puisque chaque appel se ramène au tri d’un tableaucomportant un élément de moins et on finira donc toujours par se ramener aux cas où il y a moins de 2éléments.

 Notez que nous ne pouvons pas modifier la taille d’un tableau. Nous pouvons tout au plus créer unsecond tableau et y recopier les valeurs que nous souhaitons. Toutefois, ces recopies seraient lourdes entermes de complexité. L’astuce est de rajouter un paramètre indiquant la « taille actuelle » (le tableauconserve toutes ses cases, mais nous faisons comme si il ne possédait que les taille premières).

Exemple public static void  triParInsertionRecursif(int[] tab) {

triParInsertionRecursif(tab, tab.length);}

 public static void  triParInsertionRecursif(int[] tab, int taille) {int pos;// la position où on doit insérer l’entier d’index (taille-1) int valDernierEntier ;if (taille>1) {

triParInsertionRecursif( tab, (taille-1)) ;// on va à présent insérer l’entier d’index taille-1 à sa place// Parmi les taille-1 entiers déjà triés.

pos=taille-1 ; valDernierEntier = tab[taille-1] ;while ((pos>0) && (tab[pos-1]>tab[pos])) {

tab[pos] tab[pos-1] ;pos -- ;

}

tab[pos]  valDernierEntier ;}

}

Page 118: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 118/199

 

116 

Quelques stratégies  Programmation Algorithmes récursifs et l’approche « Diviser pour régner »  [email protected] – B227 

d  – Récursivité  indirecte 

La forme de récursivité que nous venons de voir est dite directe  car l’algorithme fait directementappel à lui-même. Mais un algorithme A peut appeler un algorithme B qui appelle un algorithme C faisantappel à A. On parle alors de récursivité indirecte. Dans le cas particulier restreint à deux algorithmes (A

appelle B et B appelle A) on dit que les algorithmes sont mutuellement récursifs.

 Exemple : Les fonctions pair  et impair  

La tâche à accomplir est de retourner true si et seulement si le paramètre entier est pair. Une versiondirectement récursive consiste à voir que si n>1 alors n est pair si et seulement si (n-2) est pair. Les castriviaux sont pair(0) et pair(1). Notons qu’on ne peut pas se contenter d’uniquement l’un de cescas triviaux car un appel à pair(n) avec n pair va petit à petit se ramener au cas pair(0) alors qu’unappel avec n  impair va se ramener petit à petit au cas pair(1)  (mais jamais pair(0)). Il nous faut

donc préciser les deux cas pour être sûr de retourner un résultat dans tous les cas !Exemple public static boolean pair(int n) {

switch (n) {case 0 : return true;  break;case 1 : return false; break;default : return pair(n-2); break;

}}

Si à présent nous avons à écrire à la fois une fonction pair et une fonction impair, nous pourrions

vouloir qu’elles s’appuient l’une sur l’autre. En effet, si n>1, n est pair si (n-1) est impair et n est impairsi (n-1) est pair. Ce qui nous donne les fonctions mutuellement récursives suivantes :

Exemple public static boolean pair(int n) {

if (n==0) {return true;

}else {

return impair(n-1);}

}

 public static boolean impair(int n) {if (n==0) {return false;

}else {

return pair(n-1);}

}

Page 119: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 119/199

Quelques stratégies  Programmation Algorithmes récursifs et l’approche « Diviser pour régner »  [email protected] – B227 

117 

5.2.2.  « Diviser pour régner »

a – Principe 

Il s’agit d’une approche descendante (« top-down » en anglais) qui ramène la tâche à la combinaison

de solutions de tâches plus simples. On retrouve cette approche dans la vie courante. Par exemple, unétudiant devant faire un rapport, va d’abord décomposer l’ensemble des informations qu’il veut livrer enchapitres. Ecrire un chapitre va de même consister à répartir le contenu entre divers sections, et chaquesection sera décomposée en sous-sections. Le véritable travail de rédaction n’intervient que quand lecontenu apparaît suffisamment homogène et de petite taille pour ne pas mériter une subdivision. Lacombinaison des parties rédigées pour en faire un tout cohérent consiste le plus souvent en unregroupement avec généralement quelques phrases de transition.

Les étapes de la résolution sont les suivantes :

1  – Décomposition : on décompose la tâche en un ensemble de sous-tâches plus simples à traiter  

2  – Résolution des sous‐tâches : on recherche le résultat de chacune des sous-tâches 

3  – Combinaison : on combine les résultats des sous-tâches pour obtenir celui de la tâche globale  

Ce schéma est finalement très proche de celui des algorithmes récursifs, si ce n’est qu’il n’est passpécifié que les sous-tâches soient de même type que la tâche globale. Un algorithme basé sur la stratégie« diviser pour régner » peut donc être récursif (et dans ce cas les sous-tâches sont de même nature que latâche principale) ou pas.

b – Exemples 

 La recherche dichotomique

 Nous avons déjà abordé la recherche dichotomique dans le cadre des algorithmes itératifs (cf. p. 108).Cet algorithme s’appuie sur la stratégie diviser pour régner puisqu’il sépare la tâche de trouver un entierdans un tableau d’entiers trié en ordre croissant en deux sous problèmes (trouver l’entier dans la moitiégauche ou droite du tableau). Le tableau étant trié, la valeur située en milieu de tableau nous permetd’éliminer l’une de ses tâches et de se ramener par conséquent à une seule sous-tâche.

Puisque nous avons vu la version itérative de cet algorithme, écrivons une version récursive (on peutle faire puisque la sous-tâche est de même type que la tâche principale). Considérons que notre tableaucomporte taille entiers et que nous savons déjà rechercher un entier dans un tableau d’entiers trié dansun ordre croissant comportant moins de taille  entiers. Chaque plage d’index [i, j] i>=0, j<taille comportant moins de taille index identifie une sous partie stricte de notre tableau triéedans l’ordre croissant. On peut donc s’appeler récursivement sur l’une quelconque de ces parties. Commenous l’avons déjà vu, si l’élément du milieu est plus petit (resp. plus grand) que l’élément recherché (x), ilest inutile de rechercher l’entier parmi les cases d’index inférieur (resp. supérieur). Nous pouvons doncramener la recherche à celle dans une des moitiés du tableau après avoir testé l’élément du milieu. Notrerecherche peut s’arrêter dès que la plage des index où il est possible que l’entier recherché figure estréduite à une seule case puisqu’il suffit alors de tester cette case.

Page 120: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 120/199

 

118 

Quelques stratégies  Programmation Algorithmes récursifs et l’approche « Diviser pour régner »  [email protected] – B227 

Exemple public static boolean present(int[] tab, int x) {

return presentRec(tab, x, 0, tab.length-1); } public static boolean presentRec(int[] tab, int x, int borneGauche,

int borneDroite) {// Entrée : borneGauche<=borneDroite

// Sortie : retourne true si et seulement si x figure dans le

// tableau tab entre les index borneGauche et borneDroite (inclus).

if (borneGauche==borneDroite) {return (tab[borneGauche]==x);

}else {

int milieu = (borneGauche+borneDroite)/2;if (tab[milieu]<x) {

return presentRec(tab, x, milieu+1, borneDroite);}else {

return presentRec(tab, x, borneGauche, milieu);}

}}

 Le tri par fusion

Comment le principe du diviser pour régner peut nous conduire à une nouvelle façon de trier.Supposons tout d’abord que nous savons déjà trier tout tableau plus petit. Si on s’appelle récursivementsur une partition de notre tableau, on obtient la version triée de chaque partie. Comment obtenir la version

triée de tout notre tableau à partir de ces bouts de tableaux triés ? Quelle peut bien être l’étape decomposition et quel est son coût ? Regardons un exemple où nous coupons en deux parties (pas forcémentde même taille) notre tableau.

Le premier élément de notre tableau trié est facile à trouver : il ne peut être que le plus petit élément dela partie gauche ou le plus petit élément de la partie droite. Lequel ? Le plus petit des deux puisqu’on onveut le plus petit élément de tout le tableau.

Entrée

première partie deuxième partie

Appel récursif Appel récursif

composition

8 3 33 7 40 14 2 11 19 6 22 13 5 17 9 10 18 32 16 65

2 3 7 8 14 33 40 5 6 9 10 11 13 16 17 18 19 22 32 65

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

composition

2 3 7 8 14 33 40 5 6 9 10 11 13 16 17 18 19 22 32 65

2 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

Page 121: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 121/199

Quelques stratégies  Programmation Algorithmes récursifs et l’approche « Diviser pour régner »  [email protected] – B227 

119 

Le deuxième élément est le deuxième plus petit entier. Vu qu’on a déjà placé le plus petit, c’estforcément le plus petit parmi les éléments pas encore rangés. Comme nos deux parties sont triées, on peutse contenter de regarder les plus petits éléments de ces parties et choisir 3 entre 3 et 5 puisqu’il est le plus

 petit des deux.

On peut poursuivre ainsi à choisir systématiquement le plus petit élément entre les plus petits élémentsnon rangés des différentes parties et obtenir notre 3ème entier.

Et poursuivre encore jusqu’à avoir rangés tous les éléments.

Combien coûte cette fusion des deux parties triées ? Pour chaque élément à déterminer on comparedeux entiers et on retient le plus petit des deux. On fait donc un calcul en temps constant pour chaquecase de notre tableau à trier et la complexité de la fusion est donc linéaire dans la taille de la donnée (enO(n) où n est le nombre de cases de notre tableau).

Bien sûr, on a tout intérêt à équilibrer les deux parties : si on divise notre tableau en une partie de(taille-1) cases et une autre d’une seule case, le tri par fusion se résumerait à un tri par insertion.

L’algorithme fusionner ci-dessous réclame de l’ordre de O(n) opérations où n est le nombre decases à trier. L’algorithme de tri par fusion faisant deux appels récursifs sur des plages de cellules deuxfois plus petites et une fusion, son nombre d’opération C(n) est tel que C(n)=2C(n /2)+k n+l où k et l sontdeux constantes positives. La complexité du tri par fusion est donc en O(nlog(n)).

composition

2 3 7 8 14 33 40 5 6 9 10 11 13 16 17 18 19 22 32 65

2 3 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

composition

2 3 7 8 14 33 40 5 6 9 10 11 13 16 17 18 19 22 32 65

2 3 5 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

Entrée

première partie deuxième partie

Appel récursif Appel récursif

composition

8 3 33 7 40 14 2 11 19 6 22 13 5 17 9 10 18 32 16 65

2 3 7 8 14 33 40 5 6 9 10 11 13 16 17 18 19 22 32 65

2 3 5 6 7 8 9 10 11 13 14 16 17 18 19 22 32 33 40 65

Page 122: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 122/199

 

120 

Quelques stratégies  Programmation Algorithmes récursifs et l’approche « Diviser pour régner »  [email protected] – B227 

Exemple public static void  tri(int[] tab) {

triFusion(tab, 0, tab.length-1); }

 public static void  triFusion(int[] tab, int borneGauche,int borneDroite) {

// Entrée : borneGauche<=borneDroite

// Sortie : tri les éléments de tab situés entre les index borneGauche et

// borneDroite (inclus) en les ordonnant dans l’ordre croissant.

int milieu = (borneGauche+borneDroite)/2;triFusion(tab, borneGauche, milieu);triFusion(tab, milieu+1, borneDroite);fusionner(tab, borneGauche, borneDroite);

} public static void  fusionner(int[] tab, int borneGauche,

int borneDroite) {// Entrée : tab, un tableau d’entiers tels que les éléments d’index// compris entre borneGauche et (borneGauche+borneDroite)/2 (inclus)// soient triés dans l’ordre croissant, tout comme les éléments compris

// entre les index ((borneGauche+borneDroite)/2)+1 et bornedroite.// Sortie : les entiers situées entre les index borneGauche et bornedroite// sont réordonnés de sorte qu’ils apparaissent dans un ordre croissant.

int[] tabAux; // tableau auxliaireint milieu, pos=0; // premiere case vide dans le tableau auxiliaire

int debutG, debutD ;//premier entier pas classé de la partie gauche/droite if (borneDroite>borneGauche) {

tabAux = new int[(borneDroite-borneGauche)+1];milieu = (borneGauche+borneDroite)/2;debutG=borneGauche;debutD= (milieu+1);while ((debutG<milieu) && (debutD<=borneDroite)) {

if (tab[debutG]<tab[debutD]) {tabAux[pos] = tab[debutG];debutG++;

}else {

tabAux[pos] = tab[debutD];debutD++;

}pos++;

}// On a déjà classé dans tabAux tous les entiers de l’un des tableaux,// il ne reste plus qu’à placer les entiers de l’autre tableau

if (debutG>milieu) {for (int i=debutD; i<=borneDroite; i++) {

tabAux[pos+i-debutD]=tab[i] ;

}}else {

for (int i=debutG; i<=milieu; i++) {tabAux[pos+i-debutG]=tab[i] ;

}}

// il ne reste plus qu’à recopier les entiers de tabAux dans entiers

for (int i=borneGauche ; i<=borneDroite ; i++) {

entiers[i] tabAux[ (i-borneGauche) ] ;}

}}

Page 123: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 123/199

Conventions  Programmation Conventions de nommage  [email protected] – B227 

121 

6. Conventions

6.1.  Conventions de nommage

6.1.1.  Variables, paramètres, fonctions et procédures

Les noms attribués aux variables, aux méthodes sont des suites continues de caractères non accentuésou de chiffres commençant par une minuscule. Chaque terme composant le nom commence par unemajuscule. Le nom doit être significatif.

Exemple

- temperatureEau, nombreDeFiches  et tailleEnsemble  sont des identificateurs devariables acceptables et supprimerDernierElement, perimetreDuCercle  et

afficherPrix sont des noms de fonctions/procédures respectueux de notre convention.- maVariable et fonction126bis ne sont pas suffisamment significatifs.- TemperatureEau, nombredefiches  et tailleDeCeFichu~%£dEnsemble  ne

respectent pas la convention.

6.1.2.  Classes (Modules/Modèles)

La convention est la même mais avec des noms commençant par une majuscule.

Exemple

‐ Temperature, FicheIndividuelle et EnsembleDePoints3D sont des identificateurscorrects.

‐ NouveauType et T ne sont pas suffisamment significatifs.‐ temperature, Ficheindividuelle et Ensemble-De-% ne respectent pas la convention.

6.1.3.  Constantes

Les noms des constantes sont constitués de termes précisés en majuscules et séparés par un caractèrede soulignement ( _ ).

Exemple

‐ TEMPERATURE_INITIALE et TAUX_TVA_NORMAL_EN_FRANCE sont des noms corrects deconstantes.

Page 124: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 124/199

 

122 

Conventions   Programmation Conventions d’indentation  [email protected] – B227 

6.2.  Conventions d’indentation

Afin de rendre plus lisibles nos codes, toutes les instructions d’un même bloc doivent être alignésverticalement.

Exemple

 public static void  projectionCentrale( Point pt) {p.abscisse=0.0 ;p.ordonnee=0.0 ;

}

on aligne ces deux instructions qui font partie du même bloc 

Toutes les structures de contrôle (sauf la séquence) comportent un/des bloc(s) d’instructions qui sont àun niveau hiérarchique moindre. On laisse un même espace entre les alignements des blocs de niveauxhiérarchiques différents.

Exemple

 public static void  affichageRegion( Point pt) {// Entrée : p, un point quelconque du plan

// Sortie : affiche dans quel quart du plan se situe le point p.

if (p.abscisse>=0.0) { // il est à l’est

if (p.ordonnee>=0.0) { // il est au nord

System.out.println("quart nort-est") ;}else { // il est au sud  

System.out.println("quart sud-est") ;}

}else { // il est à l’ouest 

if (p.ordonnee>=0.0) { // il est au nord  System.out.println("quart nort-ouest") ;

}else {// il est au sud  

System.out.println("quart sud-ouest") ;}

}

} Les conditionnelles imbriquées aboutissent à plusieurs niveaux hiérarchiques. 

Exemple

 public static void  affichagePremiers( int borne) {// Entrée : borne, un entier positif

// Sortie : affiche les nombres premiers de [1, borne].

int index ;for ( index=1 ; index<=borne ; index++) {

if (estPremier( index )) {System.out.println( index+" " ) ;//on sépare à l’écran les nombre par un espace 

}}

} L’indentation permet de visualiser facilement l’étendue de chaque bloc. 

Sous eclipse, le raccourci <Ctrl>+<A>  vous permet de sélectionner l’ensemble du code, puis<Ctrl>+<i> indente convenablement le code sélectionné.

Page 125: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 125/199

Les  fichiers dans eclipse  Programmation Importer  un fichier source  [email protected] – B227 

123 

7. Les fichiers dans eclipse

7.1.  Importer un fichier source

Vous aurez à importer des fichiers dans eclipse, la plupart du temps via la fonctionnalité « import » deEclipse. Mais si vous n’avez qu’un (ou du moins peu) fichier contenant du code source à importer, vous pouvez effectuer un simple copier coller depuis votre gestionnaire de fichier.

Prenons l’exemple du fichier Clavier.java. Supposons que vous l’ayez enregistré depuis campus dansle répertoire c:\telechargement.

1-  Ouvrez votre gestionnaire de fichiers (Sous Windows il s’agit de l’explorateur Windows invocablevia le raccourci <>+<E>), déplacez vous dans le répertoire où se trouve le fichier à importer(ici c:\Telechargement), faites un clic-droit sur Clavier.java et sélectionnez copier .

2-  Dans Eclipse, faites un clic-droit sur le dossier src du projet dans lequel vous désirez importervotre fichier (ici dans le dossier src du projet PointsDuPlan) puis sélectionnez Paste.

Vous pouvez également faire un copier-coller de fichiers depuis l’un de vos projets vers un autre.

Page 126: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 126/199

 

124 

Les  fichiers dans eclipse  Programmation Importer une archive zip contenant un projet  [email protected] – B227 

7.2.  Importer une archive zip contenant un projet

Ce chapitre montre la procédure la plus sûre pour déposer un document sur campus. Il est vivementrecommandé de s’exercer sur la plate forme en utilisant les liens de dépôt mis en place. Cette section netraite que des liens de dépôt de fichier unique car ce sont ceux soulevant le plus de problème. En pratique,

des liens permettant le dépôt de plusieurs fichiers pourraient être utilisés.1-  Dans le menu File  de Eclipse, sélectionnez Import…  puis General | Existing Projects intoWorkspace. Cliquez ensuite sur le bouton Next>.

2-  Cliquez sur Select archive file puis sur le bouton Browse  situé sur la même ligne afin d’allersélectionner le projet à importer (dans l’exemple il s’agit du fichierc:\Telechargement\Rushour.zip). Enfin, cliquez sur Finish.

Page 127: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 127/199

Les  fichiers dans eclipse  Programmation Exporter  un projet sous forme d’archive zip  [email protected] – B227 

125 

7.3.  Exporter un projet sous forme d’archive zip

Si vous n’avez à déposer qu’un seul fichier source sur campus, celui-ci figure dans votre workspace etil vous suffit de sélectionner ce fichier lors de votre dépôt sur campus (cf. chapitre suivant). Cependant,vous aurez bien souvent à réaliser plusieurs fichiers et vous serez alors amené à déposer une archive

contenant l’ensemble de votre projet.1-  Dans Eclipse, faites un clic-droit sur le projet que vous désirez exporter sous forme d’archive(PointsDuPlan dans l’illustration ci-dessous) puis sélectionnez Export… 

2-  Sélectionnez ensuite General | Archive file puis cliquez sur Next>.

Page 128: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 128/199

 

126 

Les  fichiers dans eclipse  Programmation Ajouter une bibliothèque Jar à son projet  [email protected] – B227 

3-  Vérifiez qu’il y a bien une coche en face du projet à exporter (ici PointsDuPlan) puis indiquezl’emplacement et le nom de l’archive à créer (ici c:\Telechargement\PointDuPlan.zip ) en facede To archive file. Cliquez enfin sur Finish.

4-  L’archive se crée à l’emplacement indiqué et c’est elle qu’il vous faudra déposer sur campus.

7.4.  Ajouter une bibliothèque Jar à son projet

Vous n’aurez pas toujours le code source d’une partie de programme à intégrer à votre projet. C’estgénéralement le cas de bibliothèques que vous récupèrerez sur internet. Voyons comment indiquer àEclipse qu’il faut utiliser une certaine bibliothèque Jar pour un projet.

1-  Faites un clic-droit sur le projet qui doit utiliser la Bibliothèque puis cliquez sur Properties. Dansla fenêtre qui s’ouvre, cliquez à gauche sur Java Build Path et dans le volet droit sélectionnezl’onglet Libraries. Il ne vous reste qu’à indiquer le fichier jar en cliquant sur Add External JARs avant de cliquer sur OK.

Page 129: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 129/199

Dépôt de fichiers sur campus  Programmation La procédure  [email protected] – B227 

127 

8. Dépôt de fichiers sur campus

Le dépôt de fichiers sur campus n’est pas une opération compliquée, loin de là, mais certains travers peuvent conduire à ne pas déposer convenablement son document. Face à la non restitution d’un devoir,

ou à la remise d’un mauvais fichier, l’évaluateur ne peut qu’attribuer une note de 0.Ce chapitre montre la procédure la plus sûre pour déposer un document sur campus. Il est vivementrecommandé de s’exercer sur la plate forme en utilisant les liens de dépôt mis en place. Cette section netraite que des liens de dépôt de fichier unique car ce sont ceux soulevant le plus de problème. En pratique,des liens permettant le dépôt de plusieurs fichiers pourraient être utilisés.

8.1.  La procédure

Lors des TP vous aurez fréquemment à rendre des fichiers complétés par vos soins.1 – N’attendez pas la dernière minute. Prévoyez au moins 5 minutes pour le dépôt de vos fichiers.2 – Ouvrez un navigateur internet (préférablement firefox) et allez sur campus ( campus.emn.fr ).3 – Identifiez-vous puis allez sur la page du cours de programmation impérative.4 – Vérifiez que votre nom apparaît bien après la mention « Connecté sous le nom  » en haut

d’écran, et ré-ouvrez une session à votre nom si ce n’est pas le cas.

5 – La page dispose d’un lien de dépôt (identifiable par le logo et la mention Lien de dépôt),pour chaque fichier à rendre. Cliquez sur le lien Lien de dépôt : fichier Message.java.

6 – Le nom du fichier à déposer vous est rappelé ainsi que les heures de dépôt. Cliquez sur le bouton.

5

4

Page 130: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 130/199

 

128 

Dépôt de fichiers sur campus  Programmation La procédure  [email protected] – B227 

7 – La page qui apparaît comporte une zone de dépôt symbolisée par un cadre en pointillé (cf. (a)).Vous allez devoir faire glisser le fichier désiré sur cette zone. Vous pouvez glisser le fichier soitdepuis eclipse (s’il s’agit d’un fichier source comme ici Message.java) soit depuis un gestionnairede fichiers (pour par exemple déposer l’archive correspondant à l’export d’un projet). Une fois lefichier glissé sur la zone en pointillée, la zone indique le nom du fichier et vous devez ensuite

cliquer sur le bouton (cf. (b)). Attention : il vous sera souvent remis un fichier à trousqu’il vous faudra compléter pendant le TP. Veillez à bien spécifier la version complétée et non laversion à trous. Le risque de confusion est particulièrement élevé lorsqu’on utilise l’environnementEclipse (ce qui sera le cas pendant le cours de programmation par objets) car la version complétéede votre fichier ne figurera pas dans le répertoire que vous avez spécifié lors du téléchargement dufichier mais dans un autre répertoire (le workspace). Inutile de stresser cependant car comme nousle verrons plus loin il est possible de vérifier le contenu d’un fichier déposé et de procéder, s’il y alieu, à autre dépôt.

8 – La page dispose à présent d’un lien vers le fichier déposé. Vérifiez le contenu du fichier encliquant sur ce lien.

9 – Si le contenu du fichier ne correspond pas au fichier que vous vouliez remettre, cliquez sur pour supprimer de campus le fichier déposé (cliquer sur le fichier puis sélectionner

« supprimer ») et procéder à un autre dépôt.

(a) 

(b)

Page 131: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 131/199

Dépôt de fichiers sur campus  Programmation La procédure  [email protected] – B227 

129 

10 – Pour revenir à la page d’accueil du cours cliquez sur l’intitulé court du cours « PROG_A1S1 »en haut de page. 

Page 132: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 132/199

 

130 

Dépôt de fichiers sur campus  Programmation Erreurs à ne pas commettre  [email protected] – B227 

8.2.  Erreurs à ne pas commettre

8.2.1.  Déposer via la session d’un autre

Un ennui avec l’ordinateur (comme un problème d’accès au réseau) peut conduire à utiliserl’ordinateur d’un autre élève pour déposer son fichier sur campus. Il faut alors utiliser un support tel uneclé USB pour transférer le fichier sur l’ordinateur mais aussi penser à s’identifier sur campus. En effet, sion utilise la session d’un autre élève, on va déposer sur son compte et écraser le fichier qu’il avait déposé.L’étape de vérification 4 est cruciale pour éviter cette erreur.

8.2.2.  Déposer un mauvais fichier

Il est tout aussi facile de se tromper entre plusieurs versions d’un même fichier que de cliquer sur lemauvais fichier à l’étape 7. C’est pourquoi il est très important de systématiquement vérifier le contenudu fichier qu’on a déposé (étape 9).

8.2.3.  Ecraser un fichier

Avec les liens de dépôt précisant la remise d’un unique fichier, il faut garder à l’esprit qu’ il y a un liende dépôt par fichier à rendre et qu’il faut par conséquent revenir à la page d’accueil du cours après undépôt si on veut procéder à un autre dépôt. Si on procède à plusieurs dépôts via un tel lien, seul le dernierfichier déposé sera sur campus (il aura écrasé les précédents dépôts).

Si par contre le lien précise le dépôt de plusieurs fichiers, il est inutile de revenir à la page principale puisque c’est le même lien qui sera utilisé pour tous ces fichiers. Pour éviter toute erreur, l’important c’estde systématiquement vérifier ses dépôts.

Page 133: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 133/199

Principaux messages d’erreur  Programmation Messages du compilateur  [email protected] – B227 

131 

9. Principaux messages d’erreur

Cette liste n’est pas exhaustive et ne mentionne notamment pas les messages relatifs à une mauvaiseutilisation de concepts de Java non vus dans le cadre de ce cours. Il en va de même pour les listes de

causes où seules les raisons les plus courantes conduisant à l’apparition des messages sont présentées.Vous trouverez sur campus les fichiers donnés en exemple des diverses causes.

9.1.  Messages du compilateur

[ expected ’[’ expected

Des crochets ont été oubliés à l’emplacement indiqué (ex. CrochetsExpected.java).

{ expected ’{’ expected

Il manque une accolade ouvrante ou un point virgule a été placé par erreur juste avant l’accolade (ex.AccoladeOuvranteExpected.java). Attention, l’endroit indiqué n’est pas toujours exactement l’endroit oùl’accolade manque.

} expected ’}’ expectedIl manque une accolade fermante ou un point virgule a été placé par erreur juste avant l’accolade. Attention,l’endroit indiqué n’est pas toujours exactement l’endroit où l’accolade manque.

.Class expected ’.class’ expected

On a utilisé un paramètre ou une variable dans une expression en précisant inutilement son type : le typen’est à préciser que lors de la déclaration, seul le nom doit apparaître lors d’une utilisation(ex. ClassExpected.java).

; expected ’ ;’ expected

- On a oublié un point-virgule après une instruction (ex. PointVirguleExpected1.java).- Une accolade a été oubliée à la ligne précédente (ex. PointVirguleExpected2.java).- Une erreur de frappe a conduit à la présence d’un caractère inattendu à cet endroit du code (ex.

PointVirguleExpected3.java).

- Vous avez mis == au lieu de = lors de l’initialisation d’une variable (ex. int i==2; au lieu de int i=2;).- Un signe de concaténation (+) a été oublié (ex. PointVirguleExpected4.java).

 Al ready defined <var> is already defined in <methode>

Une variable est redéfinie (elle est définie alors qu’elle l’est déjà). Vérifiez notamment s’il ne s’agit pas de ladéclaration d’une variable portant le même nom que l’un des paramètres (ex. AlreadyDefined.java etAlreadyDefined2.java).

 Al ready defined <methode> is already defined in <class>

Une méthode portant le même nom et ayant des paramètres de mêmes types est déjà déclarée. On peutavoir des méthodes portant le même nom pour peut qu’elles diffèrent par le nombre ou par les types deleurs paramètres (ex. AlreadyDefined3.java).

Cannot be applied <methode> in <class> cannot be applied to <methodeBis>

On appelle une méthode sans respecter le nombre et le type des paramètres requis (ex.CannotBeApplied.java).

Cannot be dereferenced <typeDeBase> cannot be dereferenced

On appelle une méthode sur une variable ayant un type de base comme si il s’agissait d’un objet(ex. CannotBeDereferenced.java).

Cannot resolve symbol Cannot resolve symbol

- On a oublié de déclarer la variable mentionnée (ex. CannotResolveSymbol1.java).- On utilise une variable en dehors de sa portée (ex. CannotResolveSymbol2.java et

CannotResolveSymbol3.java).- On a fait une erreur dans le nom d’une variable ou d’une méthode (ex. CannotResolveSymbol4.java).- On a oublié de mettre des parenthèses () lors de l’appel d’une méthode ne prenant aucun paramètre

(ex. PointVirguleExpected5.java).- On fait référence a une classe dont le fichier contenant la définition reste introuvé (ex.CannotResolveSymbol6.java).

Page 134: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 134/199

 

132 

Principaux messages d’erreur  Programmation Messages du compilateur  [email protected] – B227 

Princi aux messa es d’erreur 

 

Cannot return … cannot return a value from method whose result type is void

Une procédure ne peut pas retourner de valeur : soit vous avez par erreur mentionné une instructionreturn dans une procédure, soit vous avez par mégarde précisé void  au lieu du type retour de votrefonction (ex. CannotReturn.java).

Class should bedeclared in a file

<class> is public, should be declared in a file named <class>.java

On a déclaré une classe publique dans un fichier qui ne porte pas le nom de la classe. Notez que cetteerreur se produira inévitablement si on déclare plus d’une classe publique dans un même fichier(ex. ClassShouldBeDeclaredInAFile.java).

Class or interfaceexpected

‘class’ or ‘i nterface’ expected.

Du code a été écris en dehors d’une classe, potentiellement à cause d’une erreur sur les accolades ou paroubli de la déclaration de la classe (ex. ClassOrInterfaceexpected1.java, ClassOrInterfaceexpected2.java etClassOrInterfaceexpected3.java).

Duplicate case label Duplicate case label

Dans un branchement (switch), un cas a été dupliqué (ex. DuplicateCaseLabel.java).

Identifier expected <identifier> expected

Java s’attend à trouver un identificateur à l’endroit désigné. Parmi les causes possibles on peut noterl’utilisation d’un mot réservé du langage en guise d’identificateur ou l’oubli de la précision du type dans ladéclaration d’une constante (ex. IdentifierExpected.java).

Illegal escape character Illegal escape character

Vous avez précisé une séquence d’échappement autre que \t (tabulation), \n (passage a la ligne), \\ (back slash), \" (doubles guillemets), \' (simples guillemets), \b  (backspace/effacement), \u (caractèreunicode), \r  (retour de chariot/retour en début de ligne) et \ suivi d’un nombre dans une chaîne decaractères (ex. IllegalEscapeCharater.java).

Illegal start ofexpression

Illegal start of expression

Il y a une erreur de syntaxe à l’endroit désigné par le compilateur. La cause peut, entre autres, être due à :- Une déclaration de constante dans une méthode. Les constantes doivent être déclarées au même niveauque les variables d’instances, et donc en dehors de toute méthode (ex. IllegalStartOfexpression1.java).

- Vous avez déclaré une méthode à l’intérieur d’une autre méthode (les déclarations de méthodes doiventse faire les une après les autres et non de façon imbriquée) (ex. IllegalStartOfExpression2.java).

- Un espace entre le + et le = d’un += (ex. IllegalStartOfExpression3.java).- Dans un switch, vous avez placé la valeur d’un case après les :  plutôt qu’avant(ex.IllegalStartOfExpresion4.java).

Illegal start of type Illegal start of type

Vous avez par erreur précisé void à la place du type d’un paramètre (ex. IllegalStartOfType.java).

Incompatible types Incompatible types

Les types sont incompatibles. On cherche par exemple à affecter une variable de type numérique avec unechaîne de caractères (ex. IncompatibleTypes.java).

Invalid flag Invalid flag

Se produit notamment lorsqu’on oublie de mentionner l’extension « .java » du fichier à compiler, si parexemple on précise la commande « javac MaClasse » au lieu de « javac MaClasse.java ».

Invalid methoddeclaration

Invalid method declaration : return type required

On a oublié de préciser le type retour (ou void) pour la méthode précisée (ex.InvalidMethodDeclaration.java).

Missing method body Missing method body, or declare abstract

Un point-virgule a été place par erreur avant le corps de la méthode (ex. MissingMethodBody.java).

Missing return statement Missing return statementUne fonction doit obligatoirement comporter une instruction return (ex. MissingReturnStatement.java).

Page 135: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 135/199

Principaux messages d’erreur  Programmation Messages du compilateur  [email protected] – B227 

133 

Non-static method Non-static methode <methode> cannot be referenced from a staticcontext

Une méthode d’instance (non statique) a été appelée depuis une méthode statique ou comme une méthodede classe au lieu d’être appelée sur une instance (un objet) (ex. NonStaticMethod.java).

Non-static variable Non-static variable <var> cannot be referenced from a static context

Une méthode statique (de classe) ne peut pas manipuler de variables d’instances (non statiques)(ex. NonStaticVariable.java).

Not a statement Not a statement

A l’endroit indiqué on trouve une expression qui contrairement à ce qu’espérait le compilateur n’est pas uneinstruction. Ce problème se présente notamment quand :- Un nom de variable commence par un chiffre (ex. NotAStatement1.java).- Un ; s’est glissé parmi une série de concaténations (ex. NotAStatement2.java).- Un == a été précisé au lieu d’un = pour une affectation (ex. NotAStatement3.java).- Un espace a été placé par erreur entre le + et le = d’un += (ex. NotAStatement4.java).

Operator || Operator || cannot be applied to int ,int

L’opérateur || doit être placé entre deux expressions à valeur booléenne et non entre deux entiers. Cette

erreur peut notamment se produire lorsqu’on confond le test d’égalité (==) avec l’affectation (=) (ex.Operator.java).

Operator && Operator && cannot be applied to int,int

L’opérateur && doit être placé entre deux expressions a valeur booléenne (et non entière). Cette erreur peutnotamment se produire lorsqu’on confond le test d’égalité (==) avec l’affectation (=), comme par exempledans l’expression if ((i=2) && (j=3))au lieu de if ((i==2)&&(j==3)).

Possible loss of … Possible loss of precision

On affecte une valeur à une variable ne pouvant potentiellement pas contenir cette valeur avec autant deprécision. Cette erreur survient par exemple lorsqu’on affecte une variable de type float avec une valeur detype double (ex. PossibleLossOfPrecision.java). Préciser explicitement le casting (comme dansfloat f=(float)2.0 ;) peut régler le problème.

Variable might not… Variable <var> might not have been ini tializedOn utilise une variable avant de l’avoir initialisée (ex. VariableMightNot.java) ou la variable est initialisée ausein d’une conditionnelle avant utilisation mais le compilateur ne parvient pas à se convaincre qu’elle serainitialisée dans tous les cas (ex. VariableMightNot2.java).

Unclosed characterliteral

Unclosed character literal

Un guillemet simple ' a été oubliée dans une expression de type caractère. Le caractère doit être entre deuxguillemets simples comme dans char c=’A’ ; (ex. UnclosedCharacterLiteral.java).

Unclosed string literal Unclosed string literal

Un double guillemet " a été oublié dans une expression de type String. La chaîne de caractères doit êtreentre deux double guillemets comme dans String s="Bonjour" ; (ex. UnclosedStringLiteral.java).

Unreachable statement Unreachable statementDes instructions ne pourront jamais être exécutées. Cette erreur se produit généralement lorsqu’uneinstruction return n’est pas placée en fin de fonction et qu’elle empêche l’accès aux instructions suivantes(ex. UnreachableStatement.java).

Page 136: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 136/199

 

134 

Principaux messages d’erreur  Programmation Messages de la machine virtuelle  java  [email protected] – B227 

9.2.  Messages de la machine virtuelle java

Ci-dessous figurent les principales (la liste n’est pas exhaustive) exceptions qui pourraient interromprele déroulement de vos programmes.

 Ar ithmetic exception Exception in thread " main" java.lang.Ari thmeticException: / by zeroUne division par zéro a eu lieu (ex. ArithmeticExceptionDivision.java).

 Array  index out  of  bounds Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:<index>

Les index valides pour un tableau t vont de 0 à t.length-1. Cette exception précise qu’il y a eu une tentatived’accès à la case d’index <index>, lequel n’est pas un index valide. Cette erreur est très fréquente et résultegénéralement d’une boucle dont l’index va trop loin (ex. ArrayIndex.java).

No class def found Exception in thread "main" java.lang.NoClassDefFoundError: <class>

- Vous avez précisé le nom du fichier contenant le code source ou celui contenant le bytecode au lieu dunom de la classe (par exemple vous avez lancé la commande  java PremierProgramme.java  ou java PremierProgramme.class au lieu de java PremierProgramme).

- Vous avez mal orthographié le nom de la classe : attention notamment à la différence entre majuscules etminuscules. Par exemple vous avez lancé la commande java premierprogramme alors que la classe senomme PremierProgramme).

- Vous désirez lancer un programme alors que le compilateur n’a pas écrit le bytecode de ce programme. Lecompilateur ne peut créer le bytecode interprétable par la machine virtuelle java qu’une fois qu’il nedétecte plus d’erreurs dans le code source. Il vous faut donc déboguer et réaliser une compilation avecsuccès avant de pouvoir exécuter votre programme.

- Vous avez peut-être un problème de configuration. Java utilise une variable d’environnement nomméeCLASSPATH pour trouver les fichiers .class quand il ne les trouve pas. Pour savoir si votre problème vientde là, vérifiez tout d’abord que le fichier .class figure bien dans votre répertoire courant, puis rajoutez leparamètre « -classpath . » à votre commande (Ex. : javac –classpath . PremierProgramme ). Si l’erreurn’apparaît plus c’est bien que votre problème résulte d’un mauvais classpath. Reportez-vous alors à lasection Erreur ! Source du renvoi introuvable.  page Erreur ! Signet non défini.  traitant de la

modification de la configuration.No such method Exception in thread "main" java.lang.NoSuchMethodError: main

La classe que vous spécifiez à la machine virtuelle doit comporter une méthode main.

Null pointer exception Exception in thread "main" java.lang.NullPointerException

Si une référence vaut null, c’est qu’elle ne désigne aucun objet. Ce message apparaît si on tented’accéder aux membres (d’accéder à l’une des variables d’instance ou à l’une des méthodes) d’un objetdésigné par une référence qui vaut null  (parce qu’elle n’a pas été initialisée ou parce qu’elle a étéexplicitement initialisée à null) (ex. NullPointerExceptionerror.java).

Stack overflow Exception in thread "main" java.lang.StackOverflowError

La pile est pleine. La raison est souvent une trop longue chaîne d’appels récursifs, ce qui survientnotamment lorsqu’on a mal identifié les cas d’arrêts et qu’on n’atteint jamais ces derniers (ex.

StackOverflow.java).String index out of … Exception in thread "main" java.lang.StringIndexOutOfBoundsException:

String index out of range: <index>

Les paramètres fournis à la méthode substring correspondent à des index non valides pour la chaîne decaractères sur laquelle la méthode a été appelée. (ex. StringIndex.java).

Page 137: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 137/199

Mémento  Programmation Types de base  [email protected] – B227 

135 

10.  Mémento

Ce chapitre liste des informations sémantiques et syntaxiques uniquement sur les éléments du langage java que nous utiliserons, en omettant volontairement certains concepts.

10.1.  Types de base

Type Description Exemples de valeurs

 byte Entiers signés sur 8 bitsde -27 à (27-1) (de –128 à 127)

-12,  0,  120,  0x10  (16  en 

héxadécimal), …

short Entiers signés sur 16 bitsde –215 à 215-1 (de –32768 à 32767)

-16000, 2005, 0x22, … 

int Entiers signés sur 32 bitsde –231 à 231-1 (de –2147483648 à 2147483647)

-12, 2000000000, … 

long Entiers signés sur 64 bitsde –263 à 263-1 (de –9223372036854775808 à 9223372036854775807)

-200000000000000000L, 421, … 

float Nombres à virgule flottante sur 32 bitsde 2-149 à (2-2-23).2127 

-1.0f,  3.40282347E+28, 2.5f, 6.55957f, … 

double Nombres à virgule flottante sur 64 bitsde 2-1074 à (2-2-52).21023 

-1.0d,  2.5,  6.55957, 2.8e1000, … 

char Caractères Unicode sur 16 bits '\u00e9'  (é), 'é', '\t'

(tab.), '\n' (retour à la ligne),'a', … 

 boolean Booléens true, false 

10.2.  Principaux opérateurs8 

Opérateurs logiques 

Pour des opérandes de type boolean :

Opérateur Nom Résultatx && y Conjonction / Et logique true si x et y valent true, false sinon.x || y Disjonction / Ou logique true si x ou y (ou les deux) vaut true, false sinon.! x  Négation / Non logique true si x est inférieur ou égal à y, false sinon.

Opérateurs arithmétiques 

Les opérandes doivent être de type numérique ( byte, short, int, long, float, double).Opérateur Nom Résultat Exemplesx + y Addition La somme de x et y  2+7  vaut 9, 2+7.5  vaut 9.5,

2e2+1e3  vaut 1200.0 

– x Changementde signe

L’opposé de x  -2  vaut -2 -(-1.5)  vaut 1.5 

x - y Soustraction La différence entre x et y  2-7  vaut -5, 2.35-0.35  vaut 2.0 4-0.5  vaut 3.5 

x * y Multiplication Le produit de x par y  2*7  vaut 14, 2*7.5  vaut 15.0 2*2e3  vaut 4000.0 

x / y Division Le quotient de la division de x

par y si y!=0 5/2  vaut 2, 5/2.0  vaut 2.5 5/0  erreur !!! (levée ArithmeticException) 

x % y Modulo Le reste de la division de x pary si y!=0 

5%2  vaut 1, 5.2f%2.5f  vaut 0.19999981 

5.2d%2.5d vaut 0.20000000000000018 5%0 erreur !!! (levée ArithmeticException) 

8 Dans le cadre de ce cours nous n’utiliserons pas les opérateurs bit‐à‐bit par exemple. 

9 L’utilisation d’objets de la classe BigDecimal peut permettre d’éviter ces problèmes de précision. 

Page 138: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 138/199

 

136 

Mémento  Programmation Principaux opérateurs  [email protected] – B227 

Quelques primitives de la classe Math(cf. : http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html )

Méthode RésultatMath.abs(x) La valeur absolue de x Math.cos(x) Le cosinus x 

Math.floor(x) Un double correspondant au plus grand entier inférieur ou égal à x Math.log(x) Le logarithme de x 

Math.max(x,y) Le plus grand des deux paramètresMath.min(x,y) Le plus petit des deux paramètresMath.pow(x,y) x à la puissance y Math.sin(x) Le sinus de x Math.sqrt(x)  La racine carrée de x Math.tan(x) La tangente de x 

Opérateurs de comparaison 

Pour des opérandes de type numérique ( byte, short, int, long, float, double) ou char :

Opérateur Nom Résultatx == y Égalité true si x est égal à y, false sinon.x != y Différence true si x est différent de y, false sinon.x <= x Infériorité large true si x est inférieur ou égal à y, false sinon.x < y Infériorité stricte true si x est strictement inférieur à y, false sinon.x >= y Supériorité large true si x est supérieur ou égal à y, false sinon.x > y Supériorité stricte true si x est strictement supérieur à y, false sinon.

Pour des opérandes de type boolean :Opérateur Nom Résultatx == y Égalité true si x est égal à y, false sinon.x != y Différence true si x est différent de y, false sinon.

Pour des opérandes qui sont des références :Opérateur Nom Résultatx == y Égalité true si x et y désignent le même objet, false sinon.

(Attention ! Ce n’est pas un test d’égalité entre objets !!! cf. equals )x != y Différence true si x et y ne désignent pas le même objet, false sinon.

(Attention ! Ce n’est pas un test d’inégalité entre objets !!! cf. equals)

Opérateurs d ’affectation 

Les opérandes doivent être de même type (à un transtypage près). Si les opérandes sont de typesnumériques différents, la variable réceptrice doit pouvoir accepter la valeur sans perte de précision nitroncature. Un opérateur « concaténation puis affectation » existe pour les String (cf. concaténation).

Opérateur Nom Résultat Exemplesx = y ; Affectation Affecte la valeur de y à x  Si x vaut 2, x vaut 4 après x=4; 

x += y; Addition puisaffectation

Affecte à x la somme de x et de y  Si x vaut 2, x vaut 4 après x+=2; 

x+=y; est équivalent à x=(x+y); 

x –= y; Soustraction puisaffectation

Affecte à x la différence entre x et y  Si x vaut 2, x vaut 0 après x-=2; 

x-=y; est équivalent à x=(x-y); 

x *= y; Multiplication puisaffectation

Affecte à x le produit de x par y  Si x vaut 2, x vaut 4 après x*=2; 

x*=y; est équivalent à x=(x*y); 

x /= y; Division puisaffectation

Affecte à x  le quotient de ladivision de x par  y si y!=0 

Si x vaut 2, x vaut 1 après x/=2; 

x/=y; est équivalent à x=(x/y); 

x/=0; erreur !!! (levée ArithmeticException)x %= y; Modulo puis

affectationAffecte à x  le reste de la divisionde x par y si y!=0 

Si x vaut 4, x vaut 1 après x%=3; 

x%=y; est équivalent à x=(x%y); 

x%=0; erreur !!! (levée ArithmeticException) 

Page 139: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 139/199

Mémento  Programmation Principaux opérateurs  [email protected] – B227 

137 

Opérateurs d’incrémentation/décrémentationLes opérandes doivent être de type numérique ( byte, short, int, long, float, double).

Opérateur Nom Résultat Exemplesx++  Post- incrémentation La valeur de x (avec comme effet

de bord d’incrémenter ensuite x 

de 1)

Si x vaut 2 :

 x++; incrémente x de 1  x vaut 3 

(équivalent à x=x+1; ou x+=1;) y=x++; affecte 2 à y puis incrémente

x de 1  y vaut 2 et x vaut 3 

++x Pré-incrémentation La valeur de (x+1) (avec commeeffet de bord d’avoir affecté lavaleur (x+1) à x)

Si x vaut 2 :

 ++x; incrémente x de 1  x vaut 3 (équivalent à x=x+1; ou x+=1;)

 y=++x; incrémente x de 1 puis affectela nouvelle valeur de x à y  y vaut 3 et x vaut 3 

x--  Post-décrémentation La valeur de x (avec comme effetde bord de décrémenter ensuitex de 1)

Si x vaut 2 :

 x--; décrémente x de 1  x vaut 1 (équivalent à x=x-1; ou x-=1;)

 y=x--; affecte 2 à y puis décrémentex de 1  y vaut 2 et x vaut 1 

--x Pré-décrémentation La valeur de (x-1) (avec commeeffet de bord d’avoir affecté lavaleur (x-1) à x)

Si x vaut 2 :

 --x; décrémente x de 1  x vaut 1 (équivalent à x=x-1; ou x-=1;)

 y=--x; décrémente x de 1 puis affectela nouvelle valeur de x à y  y vaut 1 et x vaut 1 

Opérateurs et primitives sur les chaînes de caractèresUne opérande de type String, l’autre opérande pouvant être n’importe quel type de base (grâce à la

conversion automatique) ou une référence sur un objet (grâce à la méthode toString()). :Opérateur Nom Résultat Exemplesx + y Concaténation Une nouvelle chaîne formée des

caractères de y  juxtaposés aprèsceux de x 

"toi et "+"moi"  vaut "toi et moi" si x vaut 2 alors ("x : "+x) vaut "x : 2" "tou"+'s' vaut "tous" 

x += y Concaténationpuis affectation

Affecte à x une nouvelle chaîneformée par la juxtaposition descaractères de y après ceux de x 

s1 et s2 de type String, i[0, s1.length()[ et j[i, s1.length()] deux entiers :Opérateur Nom Résultat

s1.equals(s2)  Test d’égalitédes chaînes

true si et seulement si s1 et s2 sont deux chaînes identiques

s1==s2 Test d’égalitédes références

true si s1 et s2 sont deux références désignant la même chaîne. 

s1.length()  longueur La longueur de la chaîne s1.s1.charAt(i)  caractère à Le caractère d’indice i dans s1 (les indices commençant à 0).

s1.substring(i,j)  sous-chaîne Retourne une chaîne composée des caractères de s1 dont l’indicefait partie de [i, j[.

Opérateur d’instanciation 

Opérateur Nom Résultat Exemplenew <classe>(<param>); new Une référence sur l’objet créé

(avec comme effet de bord d’avoirprécédemment créé l’objet

(instance de <classe>) et d’avoirappelé le constructeur adéquatavec les paramètres <param>).

s=new String("toi");

crée une instance de la classeString, l’initialise à "toi"  par lebiais du constructeur puis affecte à s

la référence de cette nouvelle chaîne  s  désigne à présent l’instance deString créée. 

Page 140: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 140/199

 

138 

Mémento  Programmation Mots réservés  [email protected] – B227 

Conversion explicite / transtypage / casting / coercition 

Pour un opérande (et un type <type>) d’un quelconque type de base (sauf boolean)10 :Opérateur Nom Résultat Exemples(<type>)x  Casting La conversion de la valeur de x dans le type <type>  ( byte)3.14 vaut 3 

( byte)(3.14+4.9) vaut 8 

(( byte)3.14)+4.9 vaut 7.9 

Opérateur ternaire 

cond ? e1 : e2; Vaut e1 si cond vaut true, et vaut e2 si cond vaut false.

Priorité des opérateurs 

 Nos implémentations utiliseront des parenthèses pour expliciter l’ordre d’évaluation d’une expressionet ne s’appuieront jamais sur la priorité des opérateurs. Il est donc inutile de connaître ces priorités.

Visibilité des membres (état / comportement) 

Niveau Résultat public Accessible depuis n’importe quelle partie du code

Si la visibilité n’est pas indiquée, l’accès correspond à un public limité au paquetage (les partiesdu programme situées dans un autre paquetage n’y auront pas accès)

 protected Accessible depuis les autres membres de la classe, mais aussi depuis les sous-classes et lesautres parties du programme situées dans le même paquetage.

 private Accessible uniquement depuis la classe (inaccessible depuis toute autre partie du programme)

 Autres mots réservés (cf . glossaire) 

C1 extends C2  Précise qu’une classe C1 hérite d’une classe C2.C implements I  Précise qu’une classe C  implémente l’interface I  et s’engage donc à fournir un code pour

toutes les méthodes précisées dans I.E instanceof T  Vaut true si et seulement si l’expression E est de type T.

static « De classe ». Une variable de classe existe en un unique exemplaire quel que soit le nombred’instances (par opposition aux variables d’instance pour lesquelles chaque instance de laclasse possède son propre exemplaire). Une méthode de classe n’est pas appelée sur uneinstance et n’a donc pas de paramètre implicite this.

super( args ) Appel d’un constructeur de la super-classe/classe-mère avec args pour paramètres.this( args ) Appel d’un constructeur de la même classe avec args pour paramètres.throw new E(s) Dans le corps d’une méthode, lève une exception de type E ayant s pour description.

throws E  Dans l’entête d’une méthode, précise qu’elle est susceptible de lever une exception de type E.

10.3.  Mots réservés

abstract boolean break byte byvalue case cast catch

char class const continue default do double else

extends false final finally float for future generic

goto if implements import inner instanceof int interface

long native new null operator outer package private

 protected public rest return short static super switch

sunchronized this throw throws transient true try var

void volatile while

10 Le transtypage peut également s’opérer sur des références sous certaines conditions. 

Page 141: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 141/199

S’exercer  ?  Programmation Les étapes  [email protected] – B227 

139 

11.  S’exercer ?

 Nombre d’élèves en difficulté le sont parce qu’ils ne savent pas comment s’exercer. Rien n’oblige àsuivre au pied de la lettre les étapes et recommandations ci-dessous, mais cette procédure « générique »

 peut permettre à certains d’identifier ce qui leur pose problème.11.1.  Les étapes

11.1.1.  Comprendre parfaitement le cahier des charges

La première étape consiste à bien cerner la tâche que doit réaliser le programme. Identifier les donnéeset les sorties. Ne pas hésiter à demander à l’encadrant des précisions si il subsiste le moindre doute. Un

 programme qui ne fait pas exactement ce qui est attendu ne sert à rien.

11.1.2.  Comment JE parviens à réaliser une telle tâche ?

C’est souvent l’étape oubliée par les élèves en difficulté. Prenez un exemple de données sur une feuillede brouillon, et réalisez « à la main » ce qui est demandé. Tachez ensuite de détailler, EN FRANÇAIS,

ce que vous faite, la séquence d’opérations que VOUS menez.11.1.3.  Quand la tâche est-elle terminée ?

La plupart des programmes nécessitent une/des boucle(s) (pour répéter une action) ou des appelsrécursifs. Dans les deux cas il convient de s’interroger sur les conditions d’arrêt.

Dans le cas d’algorithmes récursifs, cela permettra d’identifier les cas simples, ne nécessitant pasd’appels récursifs, auxquels on va se ramener.

Dans les autres cas cela permettra de cerner le type de boucle le plus adapté et les conditions àmentionner pour ces boucles. Si dans tous les cas il faudra avoir traité tous les éléments, une boucle for semble s’imposer. Si par contre on ne connait pas à l’avance le nombre de répétitions qui serontnécessaires, il y a fort à parier qu’une boucle while conviendra davantage. 

11.1.4.  S’exprimer en Java

Le code source n’est qu’une traduction de la séquence d’opérations que vous réalisez. Ne vous affolez pas si cette étape vous semble la plus compliquée car l’aisance va venir à force d’entrainement.

11.1.5.  Vérifier sa solution

Lorsqu’on travaille sur papier il faut tâcher de dérouler l’algorithme sur un exemple (se mettre à la place de l’ordinateur et exécuter pas à pas l’algorithme en écrivant notamment l’évolution des valeurs desvariables). L’étape est parfois fastidieuse car il ne faut surtout pas « sauter » des étapes car on risque alorsde ne pas aboutir au bon résultat. Votre cursus vous a poussé à savoir prendre du recul, mais ici c’est toutle contraire. Il faut dérouler l’algorithme aussi bêtement, que le ferait l’ordinateur.

Lorsqu’on est sur ordinateur, il convient de faire des tests unitaires, c'est-à-dire tester chaque méthodesur différents exemples en tâchant de couvrir le plus largement possible l’ensemble des données

 possibles. Bien sûr, le fait que le programme réalise la bonne tâche sur un exemple ne garantit pas qu’ilfonctionne correctement sur toutes les données possibles. Mais si votre programme ne fonctionne pas survotre exemple (il ne réalise pas la tâche attendue / il comporte des erreurs) vous savez qu’il vous faut lecorriger.

Des corrigés vous sont fournis et vous pouvez donc observer UNE version correcte. Si votre solutionne correspond pas à la solution et si vous avez le moindre doute sur le fait qu’elle soit correcte, il ne fautsurtout pas hésiter à m’envoyer votre programme par courriel pour que je puisse vous éclairer.

11.1.6.  Refaire l’exercice

Si vous n’étiez pas parvenus à écrire une solution correcte, laissez passer quelques jours (il ne faut pasque ce soit trop frais sinon votre cerveau aura encore l’image de la solution en mémoire) et reprenezl’exercice. Cela peut paraitre lourd, mais c’est clairement indispensable pour savoir si on a cette fois

acquis les concepts. En consultant un corrigé on a bien souvent le sentiment que c’était simple et qu’on acompris, mais ce n’est qu’en refaisant l’exercice qu’on peut en être convaincu.

Page 142: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 142/199

 

140 

S’exercer  ?  Programmation Sur un exemple  [email protected] – B227 

11.2.  Sur un exemple

Réalisons les premières étapes sur un exemple.

Exemple

 public static boolean estCroissant( int[] tab ) {// Entrée : un tableau comportant au moins 2 entiers.

// Sortie : Retourne true si les entiers dans tab sont dans un ordre

croissant. Retourne false sinon.

…}

Tout d’abord, il faut bien comprendre la tâche à réaliser. On doit retourner une valeur booléenne.true si les entiers sont bien dans l’ordre croissant, et false sinon. Donc false si on observe un entiersuivi d’un nombre inférieur. Heu... < ou <= ??? Supposons qu’après avoir demandé des précisions onnous informe que l’on parle de « strictement croissant ».

Deuxième étape, on prend un exemple et on essaye de voir ce qu’humainement on fait. Quand il s’agitde tableaux, il faut supposer que le tableau est très grand, et qu’on ne peut donc pas d’un simple coup

d’œil observer l’intégralité du tableau. Il faut au contraire se dire que notre champ visuel se limite à UNEcase. On peut bouger les yeux pour observer d’autres cases, mais on fixe toujours une seule case.

20  44  56  22  78 

On va regarder la case 20 puis la case suivante (44) pour observer que 20 est bien suivi d’un nombrestrictement plus grand. Pour l’instant c’est croissant, donc on vérifie le suivant de 44. C’est 56, donc c’estencore croissant. On compare 56 à son successeur, 22, et là on voit que ça coince. Ce n’est pas strictementcroissant !

Si j’essaye d’expliquer ce que j’ai fais en français, je pourrais dire qu’à chaque étape je regarde unecase et que je vérifie qu’elle n’est pas suivie par un nombre inférieur ou égal.

Quand est-ce que ça s’arrête ?Si c’est bien dans un ordre strictement croissant, je vais aller jusqu’à vérifier que les deux dernières

cases sont dans le bon ordre. Dans le cas contraire, je vais tomber sur un entier suivi d’un nombre plus petit ou égal avant d’avoir atteint la fin du tableau. Il ne sera pas utile que je poursuive davantage, car detoute façon je serais assuré que ce n’est pas dans un ordre strictement croissant.

Vu que je ne connais pas à l’avance le nombre d’étapes nécessaires (je peux m’arrêter après avoirconsulté deux cases ou après les avoir toutes consultées, ça dépend des valeurs contenues dans le tableau)une boucle while semble judicieuse. Complétons au fur et à mesure. Je peux m’arrêter soit parce que

 j’ai découvert une case suivie d’un nombre inférieur ou égal, soit parce que j’ai atteint la fin du tableau.Donc je continue tant que c’est croissant et que je n’ai pas atteint la fin du tableau. boolean croissant = true ;int i = 0 ;while (croissant && (i<tab.length)) {

... 

}Ce que je fais à chaque étape c’est vérifier que la case est suivie par un nombre plus grand (car sinon

ce n’est pas croissant), puis, n’oublions pas, passer à la case suivant : boolean croissant = true ;int i = 0 ;while (croissant && (i<tab.length)) {

croissant = (tab[i]<tab[i+1]) ;i++ ;

}return croissant ;

Enfin, on déroule l’algorithme sur un exemple. Si on le fait sur un tableau qui est en ordre croissant,on constatera que l’algorithme va planter car on va un pas trop loin. En effet, dans la boucle on consultela case  tab[i+1]  et il faut donc corriger la condition de la boucle en écrivant((i+1)<tab.length) au lieu de (i<tab.length). 

Page 143: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 143/199

Glossaire  Programmation Sur  un exemple  [email protected] – B227 

141 

12.  Glossaire

Certaines définitions de ce glossaire peuvent apparaître (très) simplistes. Elles pourront êtremises en relief et/ou nuancées lors de vos prochains cours, notamment celui de Programmation ParObjets. 

@param Balises javadoc permettant de renseigner les paramètres p. 52.@return Balises javadoc permettant de renseigner la valeur retournée par une fonction p. 52.( )  Les parenthèses servent à préciser un ordre sur les opérations dans une expression, à encadrer la

condition d’une conditionnelle simple ou d’une boucle while, à préciser les paramètres d’une boucle for et à préciser les paramètres d’une méthode.

{ } Les accolades précisent les limites d’un bloc d’instructions (cf. bloc d’instructions).[ ] Les crochets sont utilisés pour déclarer des tableaux et pour accéder à leurs éléments (p. 60).. La notation pointée permet d’accéder aux variables d’instances d’un objet (p. 21, 30) et pour appeler

une méthode sur un objet (p. 29).

.class Suffixe/Extension des noms de fichiers contenant du bytecode (p. 7, 9). 

.java Suffixe/Extension des noms de fichiers contenant du code source écrit en Java. :  Utilisé dans la syntaxe des branchements (switch  p. 78) et de l’opérateur ternaire ( … ? …: …  p. 138). ;  Un point-virgule est placé à la fin des instructions.+ Addition (cf. mémento p. 135).++Incrémentation de 1 (ou 1.0) (cf. mémento p. 135).-  Soustraction (cf. mémento p. 135).--Décrémentation de 1 (ou 1.0) (cf. mémento p. 135).* Multiplication (cf. mémento p. 135)./  Division (cf. mémento p. 135).%  Modulo (reste de la division) (cf. mémento p. 135).

<  Test d’infériorité stricte (cf. mémento p. 135).<=Test d’infériorité large (cf. mémento p. 135).>  Test de supériorité stricte (cf. mémento p. 135).>=Test de supériorité large (cf. mémento p. 135).=  Affectation (cf. mémento p. 135).==Test d’égalité entre références ou entre expressions ayant un type de base pour type. Attention : c’est

la méthode equals qu’il convient d’utiliser pour tester l’égalité entre deux objets (cf. mémento).+=Addition puis affectation (x+=y;  x=(x+y);) (cf. mémento p. 135).-=Addition puis affectation (x-=y;  x=(x-y);) (cf. mémento p. 135).*= Addition puis affectation (x*=y;  x=(x*y);) (cf. mémento p. 135)./=Addition puis affectation (x/=y;  x=(x/y);) (cf. mémento p. 135).

%=Addition puis affectation (x%=y;  x=(x%y);) (cf. mémento p. 135).//Marque le début de commentaires sur une ligne : le reste de la ligne est un commentaire (p. 18)./* */ Marquent respectivement le début et la fin d’une zone de commentaires (p. 18)./** */ Marquent respectivement le début et la fin d’une zone de commentaires javadoc (p. 18, 52).\n Séquence de contrôle qui placée dans une chaîne de caractères provoque le passage à ligne (p. 21).\t Séquence de contrôle qui placée dans une chaîne de caractères à afficher provoque le passage à la

 prochaine tabulation (p. 21). Accesseur   Méthode permettant de consulter (accesseur en lecture/getter) ou modifier (accesseur en

écriture/setter) une partie de l’état de l’objet. Selon le principe d’encapsulation les variables d’instancesont private et c’est donc via les accesseurs qu’on accède indirectement aux variables d’instance(p. 32). 

 Affectat ion  Opération permettant de donner une valeur à une variable. Elle est réalisée en java vial’opérateur = (à ne pas confondre avec l’opérateur de test d’égalité ==) (p. 25). 

Page 144: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 144/199

 

142 

Glossaire  Programmation Sur un exemple  [email protected] – B227 

 Agrégation   méthode permettant de définir un objet comme étant liée à plusieurs autres objets.Généralisation de la composition qui n’entraîne pas l’appartenance. Ce lien entre les classescorrespond au verbe avoir. Une classe A agrège B si une instance de A a un objet de type B (p. 25). 

 Algori thme Un algorithme est une marche à suivre non ambiguë décomposant la tâche à effectuer enune série d’opérations à réaliser. Un algorithme est correct si il aboutit en un nombre fini d’étapes à la

réalisation de la tâche pour laquelle il a été écris. Il est incorrect s’il demande un nombre infinid’étapes ou s’il peut dans certains cas ne pas aboutir à la réalisation de la tâche à effectuer.

 Analyse  Etape du développement d’un logiciel pendant laquelle on établit la stratégie à utiliser pourmener à bien la tâche (p. 8).

 Appel (fai re appel)  Invoquer au sein d’une méthode A une autre méthode B (une fonction ou une procédure) en précisant le nom de la méthode B et des paramètres effectifs pour cette méthode (et unobjet receveur si B est une méthode d’instance). Le déroulement de A est alors court-circuité poureffectuer le code de B avec les paramètres effectifs précisés. Si B est une procédure, une fois Bterminée on reprend le déroulement de A à l’instruction suivante. Si B est une fonction, le but del’appel à B est l’obtention d’un résultat et l’appel à B s’effectue dans une expression (à droite d’uneaffectation, en tant que condition d’une conditionnelle simple si B retourne un booléen, dans un calcul,en paramètre d’un autre appel, …) : à l’issue de B (après avoir atteint une instruction return dans B)on reprend le déroulement de A en remplaçant l’appel à B par la valeur retournée par B dansl’expression (p. 18, 29).

 Association  Lien entre deux classes correspondant à la relation « connaît » (p. 55).BIT (Binary digIT) Chiffre binaire, qui vaut 0 ou 1. La plus petite quantité d’information (p. 5). Bloc d’instructions Regroupement d’instructions. Les blocs sont délimités par des accolades {} (p. 25,

28, 32, 45, 65, 78). Bogue (De l’anglais Bug) Anomalie dans le fonctionnement d’un programme (p. 7). boolean Type primitif permettant de représenter des Booléens (cf. mémento p. 21, 135). break  Mot du langage marquant la fin du traitement à accomplir face à un cas identifié dans une

conditionnelle généralisée (switch) (p. 78).Bug Anomalie dans le fonctionnement d’un programme (p. 7).Bus Systéme de communication entre les composants d’un ordinateur (p.5). byte Type primitif permettant de représenter des entiers (cf. mémento p. 21, 135).

Bytecode Transcription du code source dans un langage générique proche du langage machine (p. 7, 9).case  Mot du langage introduisant le comportement à adopter en réponse à un cas identifié dans une

conditionnelle généralisée (switch) (p. 78).Casting Cf. Transtypage (p. 39).Chaîne de caractères Portion de texte représentées notamment via la classe String (p. 35).Champ Autre nom donné aux variables d’instance (p. 21).char  Type primitif permettant de représenter un caractère (cf. mémento p. 21, 135).class Mot du langage introduisant la définition d’une classe (p. 15, 20).Classe de complexité Une classe de complexité regroupe des algorithmes dont les complexités sont

identiques à une constante (multiplicative et/ou additive) près. Ex. : la classe des algorithmes en tempsconstant, celle des algorithmes à la complexité quadratique ou encore celle des algorithmes réclamantun temps exponentiel en la taille de la donnée (p. 95).

Classe fille Cf. héritage. Classe mère Cf. héritage. Classe modèle  Implémentation d’un type de données abstrait. Une classe précise l’état (la

représentation mémoire via des variables d’instance) etle comportement (les méthodes utiles à lamanipulation des objets de ce type) (p. 15, 20). 

Classe module  Regroupement de méthodes de classe (static). Une classe module peut-être vuecomme une boite à outils regroupant un ensemble de méthodes de classe. La classe Math fournie avecJava en est un exemple. Cette dernière rassemble un ensemble de méthodes mathématiques.Contrairement aux classes modèles, les classes modules n’ont pas de variables ou de méthodesd’instances et n’ont pas vocation à représenter un type de données (p. 70). 

Page 145: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 145/199

Glossaire  Programmation Sur  un exemple  [email protected] – B227 

143 

Clavier.java  Code source de la classe Clavier  permettant d’effectuer des lectures au clavier.Ce fichier doit être placé dans le répertoire contenant le code source de votre programme (p. 41). 

Clavier.lireChar() Méthode retournant un caractère lu au clavier (p. 41).Clavier.lireDouble() Méthode retournant un flottant de type double lu au clavier (p. 41).Clavier.lireFloat() Méthode retournant un flottant de type float lu au clavier (p. 41).Clavier.lireInt() Méthode retournant un entier de type int lu au clavier.Clavier.lireLong() Méthode retournant un entier de type long lu au clavier (p. 41).Clavier.lireString() Méthode retournant une chaîne de caractères lue au clavier (p. 41).Code source Transcription d’un algorithme dans un langage de programmation. Le code source d’une

application peut être compilé/interprété pour aboutir à une exécution (p. 6, 7, 9).Coercition Cf. Transtypage (p. 39).Commentaires  Annotations présentes dans un algorithme ou une implémentation en vue de faciliter sa

compréhension. Les commentaires ne modifient en rien le comportement d’un programme car ils sontignorés par les compilateurs (p. 18).

Compiler  Faire traduire par un compilateur le code source en un code exécutable par la machine. Lefruit de la compilation est généralement un fichier directement exécutable mais spécifique au système

d’exploitation pour lequel il a été compilé. En Java, la compilation via le compilateur  javac permetd’obtenir un bytecode qui est exprimé dans un langage générique proche du langage machine. Ce bytecode est ensuite interprété par une machine virtuelle (qu’on lance via la commande java) qui, elle,est spécifique au système utilisé (p. 9).

Complexité spatiale  La complexité spatiale d’un algorithme permet d’estimer comment varie laquantité de mémoire nécessaire en fonction de la taille de la donnée. Tout comme pour la complexitétemporelle, on fait abstraction des données de petites tailles et de la rapidité relative de l’ordinateur surlequel sera exécuté le programme en précisant non pas le nombre exact de cases mémoire nécessairesmais la classe de complexité à laquelle appartient l’algorithme (p. 95).

Complexité temporelle Pour estimer l’efficacité d’un algorithme on borne la quantité d’opérations àcoût unitaire requises en fonction de la taille de la donnée. Cependant, on souhaite déterminer lecomportement sur de grandes données en faisant abstraction de la puissance de la machine sur laquellesera exécuté le programme. C’est pourquoi on préfère préciser la classe de complexité de l’algorithme(en temps constant, linéaire, logarithmique, quadratique, exponentielle, …) qui ne tient pas compte des

 petites données et d’un éventuel facteur multiplicatif constant, plutôt que de déterminer le nombreexact d’opérations à effectuer. On distingue la complexité dans le meilleur cas, dans le pire des cas eten moyenne (p. 95). 

Composition Lien d’agrégation fort dans le sens ou (1) l’objet agrégé « meurt » (n’a plus de sens) sil’objet agrégeant est détruit et (2) un objet agrégé ne peut figurer que dans un seul objet composite(p. 55).

Conditionnelle Structure de contrôle permettant de réaliser une alternative : l’exécution d’une partie ducode n’a lieu que si une certaine condition est vérifiée. (p. 45).

Conception  Phase du développement d’un logiciel durant laquelle on décrit le fonctionnement de

manière non ambiguë, le plus souvent à l’aide d’un langage algorithmique (p. 8).Constante Donnée qui ne change pas. Pour une plus grande lisibilité et faciliter la maintenance tout en

réduisant les risques d’erreurs il est grandement conseillé d’utiliser des constantes nommées plutôt quedes constantes littérales (Ex. : utiliser une constante TEMP_EBULLITION initialisée à 100 plutôt quedirectement 100) (p. 72).

Constructeur   Méthode d’instance appelée après la création d’un objet, généralement en vued’initialiser ses variables d’instances. Un constructeur porte le nom de la classe modèle dont il fait

 partie et n’a aucun type retour (pas même void). On indique les paramètres du constructeur aprèsl’opérateur new (ex. : Position p=new Position(12,20); crée une instance de Position et l’initialise via le constructeur de Position  prenant 2 entiers en paramètres. L’adresse de cettenouvelle instance est mémorisée dans la nouvelle référence p) (p. 32, 57).

Copie profondre  Un constructeur réalise une copie profondre lorsqu’il initialise les variablesd’instances en dupliquant (plutôt qu’en partageant) l’information fournie en argument (p. 57).

Page 146: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 146/199

 

144 

Glossaire  Programmation Sur un exemple  [email protected] – B227 

Copie superficielle  Un constructeur réalise une copie superficielle lorsqu’il initialise les variablesd’instances en partageant (plutôt qu’en dupliquant) l’information fournie en argument (p. 57).

Corps  Le corps d’une boucle est le bloc d’instruction exécuté potentiellement plusieurs fois par la boucle. Le corps d’une méthode est le bloc constituant son code source (p. 29).

Débogage  Processus de mise au point visant à supprimer les erreurs présentes dans un programme

(p. 9).Déclaration  Instruction définissant un nouvel identificateur. On distingue les déclarations de constantes,

de variables, de classes, d’interfaces et de méthodes. Lorsqu’il s’agit d’une variable, la déclaration permet au système de connaître son type et d’associer à l’identificateur une case, qui n’était pourl’instant pas utilisée, apte à recevoir la donnée (la valeur de la donnée elle même s’il s’agit d’un typede base, l’emplacement de l’objet s’il s’agit d’une référence). Une variable locale n’étant utilisable quedans sa portée, le système gère automatique la libération de l’espace qu’elle occupée après sortie de sa

 portée (p. 20, 22, 26, 29).default  Mot du langage introduisant le comportement à adopter par défaut (si aucun cas listé ne

correspond) dans une conditionnelle généralisée (switch)(p. 78).Déléguer  Action de transférer une requête à une classe agrégée (p. 54).Dépendance

 Il y a un lien de dépendance notamment lorsque des méthodes d’une classe A prennent en paramètre des objets d’une classe B (p. 55).Diagramme de classes Schéma utilisé en génie logiciel pour présenter les classes et les interfaces en

faisant ressortir les liens entre elles (p. 55, 86, 92).do Mot du langage introduisant le corps d’une boucle do…while (p. 73). double Type primitif permettant de représenter un nombre à virgule flottante dit « double précision »

(p. 21, 135).else  Mot du langage permettant de spécifier le bloc à effectuer dans le cas de la violation de la

condition d’une conditionnelle simple (if)(p. 45).Encapsulation L’encapsulation vise à s’abstraire de la représentation physique du concept et à garantir

la cohérence des données (en respectant les propriétés de l’état) en ne permettant pas d’accéderdirectement (mais uniquement au moyen des méthodes) aux variables d’instance d’un objet (p. 50).

En-tête (d’une méthode) Cf. Signature (p. 29).equals  Méthode testant l’égalité de deux objets (l’opérateur ==  teste quant à lui l’égalité de deux

variables de type de base ou de deux références, mais pas l’égalité de deux objets) (p. 43).Entrées  Données nécessaires à l’accomplissement de la tâche à réaliser. Dans l’analogie entre les

algorithmes et recettes de cuisine, fournir les données correspondrait à préciser le nombre de convives.Dans le cadre de la programmation d’un magnétoscope, les données sont l’heure et la date de débutd’enregistrement, la durée d’enregistrement ainsi que la chaine à enregistrer. Enfin, le programmeimplémenté dans votre machine à laver a pour donnée un nombre correspondant à la nature desvêtements à laver (coton, synthétiques, laine, blanc, couleur, …) éventuellement accompagné d’autres

 paramètres (délicat/pas délicat, demi-brassée/pleine charge, température, …) et il réalise une série demanipulations adaptées aboutissant à un linge propre (si vous n’avez pas oublié la lessive ). Préciserles données consiste à indiquer la nature des données (par le biais de leur type), à préciser un nomsignificatif et à mentionner les éventuelles limites de validité (par exemple le fait que le nombre deconvives et forcément strictement positif) (p. 8, 29).

Etat Répresentation mémoire d’un objet via des variables d’instance (p. 21).Exceptions  Dispositif permettant de gérer des conditions exceptionnelles pendant l’exécution du

 programme. Si une exception se produit, l’exécution normale du programme est interrompue etl’exception est traitée. Si une méthode est susceptible de lever une exception, tout appel a cetteméthode doit figurer dans la clause try d’un try…catch (p. 81).

Exécution Processus de déroulement d’un programme (p. 7, 9, 15).extends  Mot du langage introduisant le lien d’héritage entre deux classes (ou entre deux interfaces

comme vous pourrez le voir dans d’autres cours) (p. 91).false Valeur « faux » des Booléens (cf. mémento p. 135).

Fichier texte  Fichier dans lesquels l’information est représentée par du texte. Ces fichiers sontconsultables via un simple éditeur de texte (p. 83).

Page 147: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 147/199

Glossaire  Programmation Sur  un exemple  [email protected] – B227 

145 

Fichier binaire Fichier dans lesquels l’information est représentée par son codage binaire. Les fichiers binaires sont plus compacts que les fichiers textes (p. 83).

final Modificateur qualifiant les attributs dont la valeur ne peut être modifiée (et qui sont donc desconstantes) (p. 72).

float Type primitif permettant de représenter un nombre à virgule flottante dit « simple précision » (cf.

mémento p. 21, 135).Fonction  Ensemble d’instructions aboutissant à l’obtention d’un résultat déterminé. Les fonctions

 prennent 0, 1 ou plusieurs paramètres et retournent toujours un résultat (elles diffèrent en cela des procédures). L’unique différence avec la notion de fonction connue en mathématiques tient au faitqu’en informatique une fonction peut réaliser des effets de bords (un affichage, une impression, lamodification de certaines variables, …) en plus de fournir le résultat escompté (p. 29).

for  Structure de contrôle itérative. Nous utiliserons cette structure pour exprimer uniquement  lesrépétitions ayant un nombre de pas connu avant la boucle (nous utiliserons une boucle while si lenombre de pas est indéfini avant la boucle, car dépendant de certaines conditions) (p. 75).

Garbage col lector  Cf. Ramasse miettes.Gestionnaire de fenêtres Logiciel chargé de l’affichage et du placement des fenêtres des applications.

(p. 6).Getter  Cf. Accesseur.Héritage Concept permettant de décrire une classe par spécialisation d’une autre. Si une classe A hérite

(on dit également « étend ») une classe B, alors B  est la classe-mère ou super-classe et A  est uneclasse-fille ou sous-classe de B (p. 90).

Horloge Dispositif électronique diffusant un signal électrique booléen oscillant servant à synchroniserdes bascules synchrones. La durée du cycle est choisi de sorte à garantir que les calculs soient terminéset les résultats stabilisés au cycle d’hrologe suivant. Cette durée est donc alignée sur la durée maximal

 possible de chacun des calculs (p. 5).Identificateur   Mot défini par l’utilisateur pour nommer un concept manipulé par le programme. Un

identificateur peut être le nom d’une variable, d’une méthode, d’une constante, d’une classe, d’uneinterface, … Une convention de nommage permet de distinguer ces différents cas au premier coupd’œil (p. 20, 22, 26, 29, 121). 

if Cf. conditionnelle.Implémenter  Écrire le code source correspondant (p. 9) ou fournir le code source des méthodes listées

dans le cas de l’implémentation d’une interface (p. 87).Implémentation Etape du développement consistant à réaliser le code source (la traduction de

l’algorithme dans un langage de programmation) du programme (p. 9)).

Initialisation   Affectation d’une valeur initiale. Le compilateur Java n’accepte pas (il fait bien !) laconsultation de la valeur d’une variable qui n’a pas été préalablement initialisée (p. 28).

Instruction Opération/Commande/Primitive du langage (cf. mémento p. 135).Instance Une instance d’un type est un représentant de ce type, un exemplaire de ce type. Une variable

d’un type primitif est une instance de ce type. Une instance d’une classe est un objet auquel on accède

via une référence (p. 19). Interface (Homme-Machine) Ensemble des éléments d’interaction permettant l’échange d’informationentre l’utilisateur et le programme (p. 41).

Interface  (d’un TDA)  Vision offerte d’un concept à son utilisateur par la déclaration des méthodes permettant sa manipulation (cf. 85).

Interpréteur  Programme exécutant ligne à ligne un code source ou un bytecode, la traduction en langagemachine s’effectuant au fur et à mesure de l’exécution. Une machine virtuelle (lancée par lacommande java) interprète du bytecode (p. 7).

Interpréteur de commandes  Composant d’un système d’exploitation offrant la possibilité àl’utilisateur d’indiquer une commande à réaliser. C’est l’interface textuelle d’un systèmed’exploitation (p. 6).

int 

Type primitif permettant de représenter des entiers (p. 21, 135).

Page 148: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 148/199

 

146 

Glossaire  Programmation Sur un exemple  [email protected] – B227 

Invariant de boucle  Propriété vérifiée tout au long de la boucle. Il arrive très souvent qu’on exhibedes invariants pour prouver la correction d’un algorithme (p. 66, 103).

Langage de programmation  Langage (donc comportant une grammaire et une syntaxe) servantd’intermédiaire entre l’algorithme (exprimé sur papier dans un langage algorithmique) et le

 programme (fichier informatique en langage machine). Des outils de traduction automatique(compilateurs/interpréteurs) sont fournis avec les langages de programmation afin d’obtenir un

 programme à partir de l’implémentation d’un algorithme dans un langage de programmation. Il existede très nombreux langages généralistes (et encore plus de langages spécialisés) parmi lesquels on peutciter Ada, Algol, Basic, Caml, C, C++, C#, Cobol, Eiffel, Fortran, Forth, Haskell, Java, Logo, Oz,Pascal, Perl, PHP, Python, Prolog, Scheme, Smalltalk, … Ces langages sont regroupés en familles(langages impératif, fonctionnels, déclaratifs, à objets, concurrents). Nous nous focaliserons sur lesconcepts fondamentaux communs à l’ensemble des langages impératifs et à objets, lesquels sont deloin les plus utilisés (p. 6).

length  Attribut des tableaux indiquant leur taille. Attention  : on peut consulter cet attribut pourconnaître la taille d’un tableau mais on ne peut pas affecter cet attribut. On ne peut pas modifier lataille d’un tableau, on peut juste en créer un nouveau via l’opérateur new (p. 60).

Length() Méthode de la classe String permettant d’obtenir la longueur d’une chaîne de caractères

(p. 37).Liaison tardive  Si face à un appel de méthode la détermination de l’entête de la méthode qui sera

invoquée a lieu à la compilation (en tenant compte des types statiques), ce n’est qu’à l’exécution quela recherche du code à exécuter à lieu (depuis le type dynamique) (p. 88).

long Type primitif permettant de représenter de grands entiers (p. 21, 135). main  Méthode de classe appelée automatiquement au lancement de l’application et marquant le point

d’entrée du programme. La classe donnée en paramètre à la machine virtuelle (MaClasse  dans lacommande  java MaClasse) doit obligatoirement comporter une méthode  main  avec lesmodificateurs et les paramètres adéquats ( public static void  main(String[] arg)  )(p. 15, 18).

 Math.E Constante e (p. 72). Math.PI  Constante PI (p. 72).  Math.XXX   La classe Math contient bon nombre de primitives mathématiques. Consultez le mémento

 pour en connaître une sélection ou consultez docs.oracle.com/javase/7/docs/api/java/lang/Math.html  pour obtenir une liste exhaustive (p. 72, 135).

Membre Les membres d’une classe sont ses variables d’instance et ses méthodes (p. 48).Mémoire vive Egalement appelée RAM pour Random Access Memory, il s’agit de la mémoire dans

laquelle sont stockées les données lors de leur traitement. Elle est bien plus rapide que la mémoire demasse mais elle perd toutes les informations dès qu’elle n’est plus alimentée en électricité (p.5).

Mémoire de masse  Mémoire de grande capacité, non volatile et qui peut être lue et écrite par unordinateur (p. 6).

Méthode Fonction ou procédure applicable à un objet (une instance d’une classe) ou à une classe (dans

le cas d’une méthode de classe, introduite par le modificateur static, comme la méthode main)(p. 15, 18, 21, 29, 70).

Microprocesseur   Partie de l’ordinateur qui exécute les instructions et traite les données des programmes (p. 5).

Modificateur   Mot réservé précisant des propriétés du membre qu’il qualifie. Nous n’aborderont quecertains modificateurs (notamment public, private, static et final) (p. 29, 70, 72). 

Mot  Quantité d’information manipulée à chaque cycle par un microprocesseur. On parle d’ordinateur 16 bits, 32 bits ou encore 64 bits selon la taille des mots (p.5). 

Mot réservé  Mot du langage. Les identificateurs introduits par le programmeur doivent différer desmots réservés (cf. mémento p. 135). 

new  Opérateur permettant d’effectuer une allocation mémoire utilisé pour la création de tableaux ou

d’objets. La valeur retournée par cet opérateur est l’emplacement en mémoire (une référence donc) surl’espace alloué (p. 25, 27, 60).null Valeur d’une référence ne référençant aucune instance (p. 28).

Page 149: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 149/199

Glossaire  Programmation Sur  un exemple  [email protected] – B227 

147 

Objet Instance d’une classe (p. 24, 26). Objet receveur   Objet sur lequel est invoquée une méthode d’instance. Au sein d’une méthode

d’instance, l’objet receveur est désigné par this (p. 30). Opération à coût unitaire Opération/instruction dont le coût temporel ne dépend pas de la taille de la

donnée. Le coût d’une telle opération est donc constant. La plupart des instructions de base sont à coût

unitaire. Par abus, nous estimerons que chaque appel à une opération de saisie ou de sortie est entemps constant (p. 95).

Paramètre formel  Variable utilisée dans l’implémentation d’une méthode pour désigner un de ses paramètres (p. 30).

Paramètre effectif  Expression précisée en paramètre lors de l’appel d’une méthode (p. 30).Paresseuse (évaluation …) L’évaluation des expressions de type A&&B et A||B est dite paresseuse

car B  n’est pas nécessairement évaluée pour déterminer la valeur de l’expression. L’évaluationcommence par l’évaluation de A et selon la valeur (false pour A&&B ou true pour A||B) B n’a

 pas besoin d’être évaluée (p. 44).Passage par valeur   Seul moyen de fournir des paramètres à une méthode en java : la valeur du

 paramètre effectif et recopiée dans une variable locale à la méthode (le paramètre formel) (p. 32).

Périphérique Dispositif connecté à un ordinateur afin de lui ajouter des fonctionnalités (p. 5).Polymorphe (Code…)  Code pouvant être utilisé avec différents types. Les interfaces et l’héritage

 permettent la réalisation de code polymorphe (p. 86).Portée d’une variable Portion du programme dans laquelle la variable est définie et utilisable (p. 28). private Modificateur correspondant au plus bas niveau de visibilité. Seules les méthodes de la classe

 peuvent accéder aux variables d’instance et aux méthodes private (p. 29).Procédure Ensemble d’instructions aboutissant à la réalisation d’une tâche déterminée. Tout comme les

fonctions, les procédures prennent 0, 1 ou plusieurs paramètres. Par contre, elles ne retournent aucunevaleur (p. 29).

Processus Programmae en cours d’exécution dans la mémoire d’un ordinateur (p. 6).

Procédure principale Procédure main appelée en premier lors du lancement d’un programme. C’est

le point d’entrée du programme (p. 15, 18).Programme Ensemble ordonné d’instructions réalisables par un ordinateur dont l’exécution aboutit à

l’accomplissement d’une tâche précise. On parle également de logiciel (avec la nuance qu’un logiciel peut comporter des ressources en plus du programme comme des fichiers de données et desdocumentations) (p. 5).

Promotion Conversion implicite et automatique dans un autre type (p. 38). protected   Modificateur de visibilité. Un membre protected est accessible aux membres de la classe,

mais aussi aux membres des sous-classes et des autres classes du même package (p. 93). public  Modificateur correspondant au plus haut niveau de visibilité. Toute partie du code peut accéder

à un membre publique (p. 29).Ramasse miettes Mécanisme libérant automatiquement l’espace mémoire occupé par les objets et les

tableaux qui ne sont plus utilisés. Le programmeur n’a donc plus à veiller à libérer l’espace qu’il aalloué et dont il ne se sert plus, mais à s’assurer que plus aucune référence ne désigne un espace dont iln’a plus l’utilité (p. 28). 

Récursif  Se dit d’un algorithme qui fait appel à lui même. La récursivité peut être directe (une méthodeA fait appel à A) ou indirecte (la méthode A fait appel à la méthode B … qui fait appel à A qui fait…)(p. 110).

Redéfinition  Fournir une nouvelle implémentation d’une méthode héritée. On introduit ainsi uncomportement différent de celui de la classe mère (p. 91).

Référence  Variable dont la valeur est un emplacement mémoire. Les références permettent donc dedésigner des instances en mémoire (p. 21).

Registre Emplacement mémoire interne au proceseur. Il s’agit du type de mémoire le plus rapidementaccessible mais au cout de fabrication élevé et disponible en très faible quantité (la place dans lemicroprosseur étant limitée) (p.5).

Page 150: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 150/199

 

148 

Glossaire  Programmation Sur un exemple  [email protected] – B227 

return Instruction permettant aux fonctions de retourner une valeur. La fonction est alors interrompueet on revient au code appelant en remplaçant l’appel de la fonction par la valeur retournée (p. 31). 

Service  Méthode d’instance. On parle parfois « d’autres services » pour distinguer les méthodesd’instances qui ne sont ni des constructeurs ni des accesseurs (p. 34).

Setter  Cf. Accesseur.short

 Type primitif permettant de représenter de petits entiers (p. 21, 135).Signature (d’une méthode)  Ligne de code précisant le type retour, le nom et les paramètres

(notamment en termes de types) d’une méthode. Des commentaires sont généralement utilisés pourcompléter la description des spécifications de la méthode (p. 29).

Sorties Résultats attendus exprimés en fonction des données de manière exhaustive (on doit connaître lerésultat attendu pour tous les données possibles dans l’espace de validité) et non ambiguë (p. 29).

Sous-classe Cf. héritage. Spécification Etape du développement d’un logiciel consistant à préciser les données et à décrire la

tâche devant être réalisée en fonction de ces données (p. 7).

static Qualificatif équivalent à « de classe » (par opposition à « d’instance »). Un attribut static estune variable de classe (par opposition aux variables d’instances), c’est à dire un attribut commun à

l’ensemble des instances de la classe (et qui ne sera donc pas dupliqué pour chaque instance). Uneméthode qualifiée de  static  n’utilise et ne modifie que des variables static. Les méthodesstatic  ne sont pas appelées sur des instances (mais sur la classe) et ne possèdent donc pas devariable this (p. 70). 

String Type des chaînes de caractères. Attention, comme l’indique le ‘S’ majuscule à String, il nes’agit pas d’un type primitif mais d’une classe (p. 35, 135).

Subsomption Règle selon laquelle si A est un sous-type de B, alors une expression de type A est ausside type B (p. 86).

super Dans le corps d’une méthode d’instance, référence sur l’objet receveur vu comme un objet de lasuper classe (p. 92). 

super(…) Appel d’un constructeur de la super-classe (chaînage des constructeurs) (p. 92). 

Super-classe Cf. héritage. switch Structure de contrôle conditionnelle (choix multiples) (p. 78).System.out Sortie standard (l’écran par défaut). Les méthodes print et println appliquées sur la

sortie standard permettent l’affichage de textes (p. 41).Système d’exploitation Couche logicielle située entre le matériel et les logiciels applicatifs. Ensemble

de programmes offrant des services généraux de gestion du matériel informatique (p. 6).Tableau  Ensemble de variables consécutives de même type accessibles via un index. L’indexage

commençant à zéro, les index des éléments d’un tableau comportant n  éléments vont donc de 0  à(n-1) et t[i-1]  désigne le ième  élément du tableau t. L’espace nécessaire à un tableau doit êtrealloué avant utilisation (p. 60).

this Dans le corps d’une méthode d’instance, référence sur l’objet receveur, donc sur l’objet sur lequel

la méthode a été appelée (p. 30). this(…) Appel d’un autre constructeur de la même classe (chaînage des constructeurs) (p. 59). true Valeur « vraie » des Booléens (cf. mémento p. 135).Transtypage Conversion explicite d’une donnée dans un autre type. Des conversions implicites (la

 promotion) peuvent être automatiquement effectuées par Java afin de ne pas perdre en précision. On peut également forcer le transtypage (on dit alors qu’on réalise un Casting) (p. 39).

Type Ensemble de données ayant des propriétés communes. Les types permettent au système d’identifierla façon de représenter la donnée en mémoire et les opérateurs et primitives utilisables sur elle (et doncégalement ceux qui ne sont pas utilisables, détectant ainsi des erreurs) (p. 19).

Type dynamique Type effectif (précisé derrière l’opérateur new) de l’objet référencé (p. 88).Type statique Pour une référence, type précisé lors de sa déclaration (p. 88).Type de Données Abstrait  Abstraction d’un concept par le biais d’une interface d’une part

(définissant la vision offerte aux utilisateurs en termes de méthodes utilisables pour manipuler le

Page 151: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 151/199

Glossaire  Programmation Sur  un exemple  [email protected] – B227 

149 

concept) et d’une implémentation (composée d’une représentation en mémoire du concept et del’implémentation des différentes méthodes de l’interface) (p. 85).

Unité de calcul arithmétique et logique Partie du microprocesseur chargée de réaliser les calculs(p. 5).

Unité de contrôle Partie du microprocesseur qui commande et contrôle le fonctionnement du système.

Il génère des signaux de contrôle qui pilotent les éléments du chemin des données (p. 5).Valeur littérale Valeur donnée explicitement dans le code source. Mieux vaut utiliser des constantes

nommées que des valeurs littérales (p. 21).Variable  Emplacement mémoire stockant une donnée pouvant varier au cours de l'exécution d'un

 programme (par opposition aux constantes) et accessible via un identificateur (le nom de la variable)(p. 21, 25, 72).

Variable de classe Attribut commun à l’ensemble des instances de la classe (il n’est pas dupliqué pourchaque objet). Une variable de classe est déclarée au moyen du modificateur static (p. 72).

Variable d’instance  Un des attributs de l’instance (objet). Les variables d’instances permettent dereprésenter l’état d’un objet (p. 21).

Variable locale Variable définie dont la portée est limitée à une portion du programme (généralement àune méthode) (p. 25).

Vecteur   Tableau unidimensionnel. Les tableaux dont les éléments sont eux même des tableaux sont

multidimensionnels, comme dans le cas des matrices où la dimension est de deux (p. 60).

Visibilité Limitation sur l’accès aux variables d’instance et méthodes, spécifiée à l’aide de modificateurs(public, protected et private). Indiquez toujours explicitement la visibilité souhaitée (p. 29,93). 

void  Mot du langage marquant l’absence de type retour des procédures (p. 29).while Mot du langage utilisé dans les structures itératives while et do…while (p. 64, 73).

Page 152: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 152/199

 

150 

Glossaire  Programmation Sur un exemple  [email protected] – B227 

Page 153: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 153/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

151 

13.  Exercices de cours

13.1.  Enoncés

Déclarez des variables d’instances qui vous semblent pertinentes pour les classes ci-dessous :

 public class PolynomeSecondDegre {// Classe modélisant un polynome du second degre.

}

 public class Heure {// Classe modélisant une heure (comme 23h35 ou 6h10).

}

 public class VisABois {// Classe modélisant une vis a bois, necessitant soit un embout plat soit

// un embout cruciforme et dont la longueur et le diametre sont exprimes en

// millimetres (ex. : une vis cruciforme de 5x60).

}

Exercice PR001  Corrigé p. 175 

Retour p. 23

Page 154: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 154/199

 

152 

Exercices de cours  Programmation Enoncés  [email protected] – B227 

A quelles classes et quelles instances pourriez-vous songer à la lecture du texte ci-dessous ? Donnezdes exemples de variables d’instances pour ces classes.

 Bonjour Tristan, alors, vous avez choisi ?

-  Oui, je vais prendre une double, chocolat pistache. Pour Paul ce sera la même chose et pour Marie

 juste une boule à la fraise.

-  C’est parti !

 Et pendant que Lucie prépare les glaces, Tristan vérifie son ticket de loto… même pas trois numéros…

Exercice PR002  Corrigé p. 176 

Retour p. 23

Page 155: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 155/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

153 

En supposant que vous remplaciez le code de la méthode main de la classe Point par le code ci-dessous, qu’elle serait l’état de la mémoire juste avant le dernier affichage ?

Point pt = new Point() ;Point pt2 = new Point();Point pt3 = pt2;System.out.println("fin");

Exercice PR003  Corrigé p. 176 

Retour p. 28

Page 156: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 156/199

 

154 

Exercices de cours  Programmation Enoncés  [email protected] – B227 

-  Créez un nouveau projet java (File | New | Java project) nommé Visserie.-  Rajoutez dans ce projet une nouvelle classe (File | New | Class) nommée VisABois.

-  Complétez la classe VisABois  en rajoutant un constructeur et les accesseurs en lecture qui voussemblent judicieux.

-  Rajoutez une méthode main dans la classe. Cette méthode devra créer deux instances de vis, l’unecruciforme de longueur 40 et de diamètre 5, l’autre à tête plate de longueur 70 et de diamètre 6. Laméthode main affichera la longueur des deux vis via l’appel d’un accesseur.

 public class VisABois {// Classe modelisant une vis a bois, necessitant soit un embout plat soit

// un embout cruciforme et dont la longueur et le diametre sont exprimes en

// millimetres.

 private int longueur, diametre; // Les dimensions en mm de la vis

 private boolean cruciforme; // Vaut true si la tete de la vis necessite// un tournevis cruciforme, false sinon (embout plat).

}

Exercice PR004  Corrigé p. 176 

Retour p. 34

Page 157: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 157/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

155 

Pour chacune des lignes ci-dessous, précisez la valeur qu’aura la variable après son initialisation sicelle-ci est autorisée.

double a = 3 + 2;

int b = 3 + 2.5;

int c = (int) (3 + 2.5);

double d = (3 / 2);

double e = (3.0 / 2);

double f = ((double)3) / 2;

int g = (int) (3.0 / 2/0);

int h = "124";

int i = Integer.parseInt("124");

double j = Double.parseDouble("5.78");

String k = 5.78;

String l = ""+5.78;

int m = 'A';

char n = (char)(m+1);

char o = 65;

Exercice PR005  Corrigé p. 176 

Retour p. 40

Page 158: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 158/199

 

156 

Exercices de cours  Programmation Enoncés  [email protected] – B227 

Modifiez la procédure main  de la classe Point  de sorte qu’elle (1) affiche un message invitantl’utilisateur à saisir l’abscisse d’un point, (2) réalise la saisie d’une abscisse, (3) affiche une invitation à

saisir l’ordonnée d’un point, (4) réalise la saisie d’une ordonnée, (5) crée un point avec les coordonnéessaisies et (6) affiche le point créé.

Exercice PR006  Corrigé p. 176 

Retour p. 42

Page 159: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 159/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

157 

Ecrivez une méthode equals pour la classe VisABois sachant qu’on considère que deux vis sontégales si elles sont de même longueur et de même diamètre (même si elle ne nécessitent pas le même

embout). Testez sur quelques instances de VisABois.

Exercice PR007  Corrigé p. 176 

Retour p. 44

Page 160: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 160/199

 

158 

Exercices de cours  Programmation Enoncés  [email protected] – B227 

Une entreprise vend des articles en France et en Belgique (uniquement dans ces deux pays) et souhaiteréaliser un logiciel de facturation. Pour cela, elle souhaite modéliser ce qu’est un prix.

Complétez la méthode getTVATauxNormal()  ci-dessous sachant que :- Le code ISO 3166-1 de la France est 250 et celui de la Belgique est 56.- Le taux de TVA normal est de 19,6% en France et de 21% en Belgique.

 public class Prix { private double montantHT; private int codePays;

 public Prix(double montantHT, int codePays) {this.montantHT = montantHT;this.codePays = codePays;

}

 public double getHT() {return this.montantHT;

}

 public int getCodePays() {return this.codePays;

}

 public double getTVATauxNormal() {// retourne le montant de la TVA correspondant au prix soumis au taux

// normal dans le pays de code codePays

double tva;

if (this.getCodePays()==250) {tva = ((this.getHT()*19.6)/100.0);

}else {

tva = ((this.getHT()*21.0)/100.0);}return tva;

}}

Exercice PR008  Corrigé p. 176 

Retour p. 47

Page 161: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 161/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

159 

L’entreprise de l’exercice PR008  a à présent des succursales entre autres en Allemagne, Italie,Espagne, Estonie, Autriche et Slovénie. Le code de la méthode getTVATauxNormal()  doit donc êtremodifié en conséquence sachant que :

- Les codes ISO 3166-1 de la France, de la Belgique, de l’Allemagne, de l’Italie, de l’Espagne, del’Estonie, de l’Autriche et de la Slovénie sont respectivement 250, 56, 276, 380, 724, 233, 40 et705.

- Le taux de TVA normal est de 19,6% en France et de 21% en Belgique. En Allemagne, Italie etEspagne il est respectivement de 19%, 21% et 18%. Le taux de TVA normal est de 20% dans tousles autres pays où l’entreprise vend.

 public class Prix { private double montantHT; private int codePays;

 public Prix(double montantHT, int codePays) {this.montantHT = montantHT;this.codePays = codePays;

}

 public double getHT() {return this.montantHT;

}

 public int getCodePays() {return this.codePays;

}

 public double getTVATauxNormal() {// retourne le montant de la TVA correspondant au prix soumis au taux

// normal dans le pays de code codePays

}}

Exercice PR009  Corrigé p. 176 

Retour p. 47

Page 162: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 162/199

 

160 

Exercices de cours  Programmation Enoncés  [email protected] – B227 

Ecrivez la classe PointTab, similaire à la classe Point  mais en représentant cette fois les

coordonnées via un tableau de deux double. 

Exercice PR010  Corrigé p. 176 

Retour p. 61

Page 163: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 163/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

161 

On souhaite rajouter dans la classe SetOfBool la méthode d’en-tête suivante :

/*** @return Si l’ensemble est vide, retourne true, sinon, retourne la* conjonction des Booléens de l’ensemble de rang impair (conjonction du* premier avec le troisième, le cinquième, …)*/

 public boolean conjonctionRangImpair( ) {

…}

a) Trouvez en quoi le corps ci-dessous n’est pas adéquat. Proposez une correction.

{ boolean conjonction = true ;index = 1 ;while (index <= this.lesBooleens.length) {

conjonction = conjonction && this.lesBooleens[ index ];index = index + 2;

}return conjonction;

}

 b) Trouvez en quoi le corps ci-dessous n’est pas adéquat. Proposez une correction.

{ boolean conjonction = true ;int nbDejaConsideres = 0 ;while ((nbDejaConsideres*2)<= this.lesBooleens.length) {

conjonction = conjonction && this.lesBooleens[nbDejaConsideres*2 ];nbDejaConsideres = nbDejaConsideres + 2;

}return conjonction;

}

Exercice PR011  Corrigé p. 176 

Retour p. 69

Page 164: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 164/199

 

162 

Exercices de cours  Programmation Enoncés  [email protected] – B227 

Ecrivez une méthode principale qui demande à l’utilisateur de saisir un entier strictement positif n auclavier puis qui affiche la somme des entiers de 1 à n. On supposera, sans vérification, que l’utilisateursaisi bel et bien un entier strictement positif.

a) En utilisant une boucle while.

 b) Sans utiliser de boucle.

Exercice PR012  Corrigé p. 176 

Retour p. 69

Page 165: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 165/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

163 

Complétez la méthode somme de la classe ci-dessous modélisant un ensemble d’entiers. 

 public class SetOfInt { private int[] lesEntiers;

/*** Initialise l'ensemble pour qu'il corresponde a l'ensemble vide*/

 public SetOfInt() {this.lesEntiers = new int[0];

}/*** @return le nombre d'entiers contenus dans l'ensemble*/

 public int size() {

return this.lesEntiers.length;}/*** @param  i un entier de [ 0, this.size()-1 ]* @return l'entier d'index i (le (i+1)eme entier de l'ensemble )*/

 public int get( int i) {return this.lesEntiers[i];

}/*** @return la somme des entiers de l'ensemble*/

 public int somme() {

// A vous de compléter… 

}}

Exercice PR013  Corrigé p. 176 

Retour p. 69

Page 166: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 166/199

 

164 

Exercices de cours  Programmation Enoncés  [email protected] – B227 

Dans une classe nommée Triangulaires :

a) Ecrire une méthode de classe sommeDesEntiersJusquA(int borne) qui étant donné unentier strictement positif borne retourne la somme des entiers de 1 à borne.

 b) Ecrire une méthode de classe nombresTriangulairesInferieursA(int  borne)  quiretourne un tableau d’entiers constitué de tous les nombres triangulaire inférieurs ou égaux àborne. Votre méthode doit exploiter sommeDesEntiersJusquA. Pour rappel, les nombrestriangulaires sont 1, 3, 6, 10, 15, 21, … On obtient le ième nombre triangulaire en ajoutant i au(i-1)ème  nombre triangulaire. En d’autres termes, le ième  nombre triangulaire est la somme desentiers de 1 à i.Conseil : il va vous falloir déterminer la taille du tableau à retourner afin de l’allouer avant de leremplir. Pour cela, vous pourriez déterminer un a un les premiers nombres triangulaires sans les

mémoriser dans un tableau mais en les comptant. c) Ecrire une méthode principale affichant les nombres triangulaires inférieurs ou égaux à 100.

Exercice PR014  Corrigé p. 176 

Retour p. 70

Page 167: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 167/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

165 

Même exercice que PR009 mais avec constantes. L’entreprise de l’exercice PR008 a à présent dessuccursales entre autres en Allemagne, Italie, Espagne, Estonie, Autriche et Slovénie. Le code de la

méthode getTVATauxNormal()  doit donc être modifié en conséquence sachant que :- Les codes ISO 3166-1 de la France, de la Belgique, de l’Allemagne, de l’Italie, de l’Espagne, del’Estonie, de l’Autriche et de la Slovénie sont respectivement 250, 56, 276, 380, 724, 233, 40 et705.

- Le taux de TVA normal est de 19,6% en France et de 21% en Belgique. En Allemagne, Italie etEspagne il est respectivement de 19%, 21% et 18%. Le taux de TVA normal est de 20% dans tousles autres pays où l’entreprise vend.

 public class Prix { private double montantHT; private int codePays;

 public Prix(double montantHT, int codePays) {this.montantHT = montantHT;this.codePays = codePays;

}

 public double getHT() {return this.montantHT;

}

 public int getCodePays() {return this.codePays;

}

 public double getTVATauxNormal() {// retourne le montant de la TVA correspondant au prix soumis au taux

// normal dans le pays de code codePays

}}

Exercice PR015  Corrigé p. 176 

Retour p. 72

Page 168: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 168/199

 

166 

Exercices de cours  Programmation Enoncés  [email protected] – B227 

Modifiez les solutions de l’exercice PR011 en utilisant une boucle do…while plutôt qu’une bouclewhile si cela vous semble judicieux.

Exercice PR016  Corrigé p. 176 

Retour p. 73

Page 169: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 169/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

167 

Modifiez les solutions de l’exercice PR012 en utilisant une boucle do…while plutôt qu’une bouclewhile si cela vous semble judicieux.

Exercice PR017  Corrigé p. 176 

Retour p. 73

Page 170: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 170/199

 

168 

Exercices de cours  Programmation Enoncés  [email protected] – B227 

Sachant que l’opérateur % donne le reste de la division euclidienne ( x%y est le reste de la divisioneuclidienne de x par y), complétez la fonction suivante :

/*** @param x, un entier positif* @return true si et seulement si x est pair (false sinon)*/ 

 public static boolean estPair( int x) {

}

a) En utilisant l’opérateur %.

 b) Sans recourir à % mais en utilisant une boucle while.

c) Sans recourir à % mais en utilisant une boucle do…while.

Exercice PR018  Corrigé p. 176 

Retour p. 73

Page 171: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 171/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

169 

Complétez la méthode getTTC  de Commande  considérant que le code de la méthode getTTC  deArticle soit déjà écrit.

 public class Article { private double montantHT; private int codePays; private  boolean tauxReduit;//true si l’article est soumis à un taux réduit

 public Article (double montantHT, int codePays, boolean tauxReduit) {this.montantHT = montantHT;this.codePays = codePays;this.tauxReduit = tauxReduit;

}

 public double getHT() {

return this.montantHT;}

 public double getTTC() {…

}}

 public class Commande { private Article[] lesArticles; private int[] quantites ;// Tableau de même taille que lesArticles

// indiquant pour chaque article la quantité commandée.…/**

* @return Retourne le montant TTC de l’ensemble de la commande

*/

 public double getTTC() {

}}

Exercice PR019  Corrigé p. 176 

Retour p. 77

Page 172: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 172/199

 

170 

Exercices de cours  Programmation Enoncés  [email protected] – B227 

Complétez la méthode inverser en utilisant la boucle qui vous semble la plus judicieuse.

 public class SetOfBool { private boolean[] lesBooleens; /*** initialise l’instance de sorte qu’elle corresponde à un ensemble vide* Attention : ci-dessous on initialise la référence avec un tableau de* taille 0, ce qui est différent d’initialiser à null.*/

 public SetOfBool() {this.lesBooleens = new boolean[0];

}/**

* @return Retourne le nombre de Booléens dans l‘ensemble*/

 public int size() {return this.lesBooleens.length;

}/*** @param i, un entier de [0, this.size()[* @return Retourne le (i+1)eme Booléen de l‘ensemble*/

 public boolean get(int i) {return this.lesBooleens[i];

}/*** Inverse le (i+1)eme Booléen de l’ensemble (il devient true si* il valait false et vice versa)* @param i, un entier de [0, this.size()[*/

 public void  inverser(int i) {this.lesBooleens[i] = !this.lesBooleens[i];

}/*** A l’issue de cette methode, chacun des Booléen du tableau lesBooleens* a été invsersé : il vaut true si il valeit false et vice vera.*/

 public void inverser() {

// A vous de compléter

}}

Exercice PR020  Corrigé p. 176 

Retour p.

 77

Page 173: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 173/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

171 

Les nutritionnistes se servent fréquemment de l’Indice de Masse Corporelle (IMC, ou BMI pour BodyMass Index en anglais) comme d’un indicateur sur l’embonpoint d’un(e) patient(e). Cet indicecorrespondant au rapport entre le poids en kilo et le carré de la taille exprimée en mètre, est inférieur à 19chez les personnes minces, compris entre 19 et 21 chez les personnes de corpulence « normale », entre 22et 24 dans le cas d’un léger surpoids, entre 25 et 29 dans le cas d’un important surpoids et est supérieur ouégal à 30 dans le cas de patient(e)s obèses. Complétez la méthode getCorpulence  de la classePatient.

a) A l’aide de conditionnelles simples.

 b) A l’aide d’un branchement.

 public class Patient {

 private double poids; // en kilo  private double taille; // en mètres

 public Patient(double poids, double taille) {this.poids = poids;this.taille = taille;

} public double getPoids() {

return this.poids;} public double getTaille() {

return this.taille;

} /**

* @return retourne "Mince", "Normal", "Leger surpoids",

* "Surpoids important" ou "obese" selon la corpulence

* correspondant à l’IMC du patient.

*/

 public String getCorpulence() {// A vous de compléter

}}

Exercice PR021  Corrigé p. 176 

Retour p. 80

Page 174: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 174/199

 

172 

Exercices de cours  Programmation Enoncés  [email protected] – B227 

Ecrire la méthode nombreDeJoursDansLeMois  de la classe  Date  qui, comme son noml’indique, retourne le nombre de jours dans le mois correspondant à la date. Vous considérerez comme

déjà implémentée la méthode bissextile  retournant true  si et seulement si l’année de la date est bissextile.

 public class Date { private int jour, mois, annee; 

 public Date(int jour, int mois, int annee) {this.jour = jour;this. mois = mois;this. annee = annee;

} public int getJour() {

return this.jour;} public int getMois() {

return this.mois;} public int getAnnee() {

return this.annee;}

/*** @return true si et seulement si l’annee de la date est bissextile*/

 public boolean bissextile() {

… }

/*** @return le nombre de jours dans le mois de la date*/

 public int nombreDeJoursDansLeMois() {

// A vous de compléter

}}

Exercice PR022  Corrigé p. 176 

Retour p. 80

Page 175: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 175/199

Exercices  de cours  Programmation Enoncés  [email protected] – B227

 

173 

Donnez un exemple d’algorithme qui a sa complexité dans le pire cas en O(n) mais pas en  (n).

Exercice PR023  Corrigé p. 176 

Retour p. 102

Page 176: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 176/199

Page 177: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 177/199

Exercices  de cours  Programmation Corrigés  [email protected] – B227

 

175 

13.2.  Corrigés

Déclarez des variables d’instances qui vous semblent pertinentes pour les classes ci-dessous :

 public class PolynomeSecondDegre {// Classe modélisant un polynome du second degre.

 private double coef2, coef1, coef0 ; // Les coefficients du polynome// le polynome correspond alors a : coef2*(x*x) + coef1*x +coef1

}

 public class Heure {// Classe modélisant une heure (comme 23h35 ou 6h10).

 private int h, mn ; // Les nombres d’heures et de minutes// Les valeurs allant de 0 à 23 et de 0 à 59, n’importe quel autre type

// primitif entier (comme byte) aurait pu être choisi au lieu de int.

}

Ou

 public class Heure {// Classe modélisant une heure (comme 23h35 ou 6h10).

 private int mnDepuisMinuit ;//Le nombre de minutes écoulées depuis minuit

}

 public class VisABois {// Classe modélisant une vis a bois, necessitant soit un embout plat soit

// un embout cruciforme et dont la longueur et le diametre sont exprimes en

// millimetres. private int longueur, diametre; // Les dimensions en mm de la vis private boolean cruciforme; // Vaut true si la tete de la vis necessite// un tournevis cruciforme, false sinon (embout plat).

}

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

Corrigé PR001  Enoncé p. 151 

Retour p. 23

Page 178: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 178/199

 

176 

Exercices de cours  Programmation Corrigés  [email protected] – B227 

 Bonjour Tristan, alors, vous avez choisi ?

-  Oui, je vais prendre une double, chocolat pistache. Pour Paul ce sera la même chose et pour Marie juste une boule à la fraise.

-  C’est parti !

 Et pendant que Lucie prépare les glaces, Tristan vérifie son ticket de loto… même pas trois numéros…

On peut songer à une classe pour le type Glace. Ici, 3 instances sont évoquées : la glace de Tristan,celle de Paul et enfin celle de Marie. Pour la représentation, il semble important de coder l’informationsur le nombre de boules et les parfums. On peut supposer que la liste des parfums disponibles soit connueet donc attribuer un numéro à chacun des parfums à la carte (1-Chocolat, 2-Pistache, 3-Fraise, 4-…). Enutilisant uniquement les types primitifs11 et en supposant que les cornets comportent au plus trois boules,on peut songer à une variable entière nombreDeBoules  et trois autres variables d’instances entièresparfum1, parfum2 et parfum3 qui désignent les parfums choisis.

 Notez qu’il est possible d’avoir deux instances qui ont exactement les mêmes valeurs pour leursvariables d’instances. Ici, Tristan et Paul auront tous deux des glaces de 2 boules aux parfums chocolat et

 pistache bien qu’il s’agisse de deux glaces distinctes (ils ne partagent pas la même glace). Nous pourrions également vouloir représenter les tickets de loto. Une instance serait le ticket de

Tristan. Un ticket pourrait être représenté par les 6 valeurs de 1 à 49 qui ont été cochées et la date dutirage (On peut compléter si d’aventure on souhaite également représenter les grilles multiples, lesabonnements, …).

Enfin, on pourrait également proposer une classe Personnage  avec ici 4 instances (Tristan, Paul,Marie et Lucie).

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

11 Nous verrons d’autres types qui pourraient nous faire songer à d’autres solutions. 

Corrigé PR002  Enoncé p. 152 

Retour p. 23

Page 179: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 179/199

Exercices  de cours  Programmation Corrigés  [email protected] – B227

 

177 

La première ligne (Point pt = new Point() ;) déclare une variable locale pt et l’initialiseavec l’adresse d’un nouvel objet de type Point. La seconde ligne fait de même pour une secondevariable locale pt2. La troisième ligne quant à elle déclare une référence pt3 mais l’initialise avec lavaleur actuelle de pt2. La valeur de pt2 (l’adresse du second Point) est recopiée dans pt3 de sorteque pt3  désigne elle aussi le second Point. A l’issue de ces trois lignes la mémoire peut êtreschématisée par :

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

Corrigé PR003  Enoncé p. 153 

Retour p. 28

abscisse

ordonnee

?

?

pt

abscisse

ordonnee

?

?

pt2

Pt3

Page 180: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 180/199

 

178 

Exercices de cours  Programmation Corrigés  [email protected] – B227 

 public class VisABois {

// Classe modelisant une vis a bois, necessitant soit un embout plat soit// un embout cruciforme et dont la longueur et le diametre sont exprimes en

// millimetres.

 private int longueur, diametre; // Les dimensions en mm de la vis private boolean cruciforme; // Vaut true si la tete de la vis necessite// un tournevis cruciforme, false sinon (embout plat).

 public VisABois( int l, int d, boolean c) {// Initialise l'instance de sorte qu'elle ait l pour longueur,

// d pour diametre et c pour information sur l'embout

this.longueur = l;this.diametre = d;this.cruciforme = c;

}

 public int getLongueur() {// accesseur retournant la longueur de la vis

return this.longueur;}

 public int getDiametre() {// accesseur retournant le diametre de la vis

return this.diametre;}

 public  boolean getCruciforme() {

// retourne true si la vis requiert un embout cruciforme, false si// elle necessite un embout plat.

return this.cruciforme;}

 public static void  main(String[] args) {VisABois vis1 = new VisABois(40,5,true);VisABois vis2 = new VisABois(70,6,false);System.out.println(vis1.getLongueur());System.out.println(vis2.getLongueur());

}

}

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

Corrigé PR004  Enoncé p. 154 

Retour p. 28

Page 181: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 181/199

Exercices  de cours  Programmation Corrigés  [email protected] – B227

 

179 

Pour chacune des lignes ci-dessous, précisez la valeur qu’aura la variable après son initialisation sicelle-ci est autorisée.

double a = 3 + 2;// Autorisée, a vaut 5.0

int b = 3 + 2.5;// Interdite, 3 est convertie en 3.0, 3+2.5 vaut 5.5 et java

// interdit d’affecter cette valeur à une variable entière car cela

// causerait une potentielle perte de précision implicite.

int c = (int) (3 + 2.5);// Autorisée. 3+2.5 vaut 5.5 mais on convertit explicitement en int.

// C’est donc la valeur 5 qu’on affecte a c ce qui bien sûr ne pose

// aucun problème.

double d = (3 / 2);// Autorisée. La division est ici euclidienne car les deux opérandes

// sont entière et 3/2 vaut 1. Java effectue la conversion implicite

// de 1 en 1.0 car cela n’engendre aucune perte de précision. double e = (3.0 / 2);// Autorisée. 2 est converti en 2.0, et c’est 1.5 qu’on affecte à e. double f = ((double)3) / 2;// Autorisée. On convertit explicitement 3 en 3.0 et 2 est donc

// implicitement converti en 2.0. C’est donc 1.5 qu’on affecte à f. int g = (int) (3.0 / 2.0);// Autorisée. 3.0/2.0 vaut 1.5 qu’on convertit explicitement en 1 et

// c’est donc 1 qu’on affecte à g. int h = "124";// Interdite. Les types sont incompatibles. int i = Integer.parseInt("124");// Autorisée. On cnovertit explicitement "124" en 124 et c’est donc

// 124 qu’on affecte à i. double j = Double.parseDouble("5.78");// Autorisée. On cnovertit explicitement "5.78" en 5.78 et c’est

// donc 5.78 qu’on affecte à j. String k = 5.78;// Interdite. Les types sont incompatibles. String l = ""+5.78;// Autorisée. 5.78 est implicitement convertie en "5.78" afin de

// pouvoir être concaténée à "" et c’est donc "5.78" qu’on affecte à

// l.

int m = 'A';// Autorisée. m vaut le code de 'A', c'est-à-dire 65.

char n = (char)(m+1);// Autorisée. m+1 vaut 66, qu’on convertit explicitement en char et

// c’est donc 'B' qu’on affecte à n.

char o = 65;// Autorisée. 65 est implicitement converti en char et c’est 'A' qui

// est affectée à o.

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

Corrigé PR005  Enoncé p. 154 

Retour p. 40

Page 182: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 182/199

 

180 

Exercices de cours  Programmation Corrigés  [email protected] – B227 

 public static void  main(String[] args) {System.out.println("veuillez saisir l'abscisse d'un point");

double x = Clavier.lireDouble();System.out.println("Veuillez saisir l'ordonnee d'un point");double y = Clavier.lireDouble();Point pt = new Point(x, y);System.out.println("Le point cree est : "+pt);

}

 N’oubliez pas que vous devez placer le fichier Clavier.java dans le répertoire de votre code source.

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

Corrigé PR006  Enoncé p. 156 

Retour p. 42

Page 183: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 183/199

Page 184: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 184/199

 

182 

Exercices de cours  Programmation Corrigés  [email protected] – B227 

 public class Prix { private

 double

 montantHT; private int codePays;

 public Prix(double montantHT, int codePays) {this.montantHT = montantHT;this.codePays = codePays;

}

 public double getHT() {return this.montantHT;

}

 public int getCodePays() {return this.codePays;

}

 public double getTVATauxNormal() {// retourne le montant de la TVA correspondant au prix soumis au taux

// normal dans le pays de code codePays

double tva;if (this.getCodePays()==250) {

tva = ((this.getHT()*19.6)/100.0);}else {

tva = ((this.getHT()*21.0)/100.0);}return tva;

}

}

 Notez qu’il n’est pas utile dans le else de vérifier si le code du pays correspond à celui de la Belgique puisque l’énoncé précise que l’entreprise ne vend qu’en France et en Belgique.

Le code ci-dessous est également acceptable dans le sens où il répond bien aux spécifications de laméthode mais (1) il est moins explicite dans le sens où il ne souligne pas le caractère exclusif (le code estsoit celui de la France, soit celui de la Belgique) et (2) du fait qu’il n’exploite pas le caractère exclusif viaun else, le test (this.getCodePays()==56)   sera évalué même si on est entré dans la premièreconditionnelle du fait que le code est 250. Le code ci-dessous est donc moins judicieux.

// Solution alternative moins judicieuse

 public double getTVATauxNormal() {// retourne le montant de la TVA correspondant au prix soumis au taux

// normal dans le pays de code codePaysdouble tva=0.0;if (this.getCodePays()==250) {

tva = ((this.getHT()*19.6)/100.0);}if (this.getCodePays()==56) {

tva = ((this.getHT()*21.0)/100.0);}return tva;

}}

Corrigé PR008  Enoncé p. 158 

Retour p. 47

Page 185: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 185/199

Exercices  de cours  Programmation Corrigés  [email protected] – B227

 

183 

 public class Prix { private double montantHT;

 private int codePays;

 public Prix(double montantHT, int codePays) {this.montantHT = montantHT;this.codePays = codePays;

}

 public double getHT() {return this.montantHT;

}

 public int getCodePays() {return this.codePays;

}

 public double getTVATauxNormal() {// retourne le montant de la TVA correspondant au prix soumis au taux

// normal dans le pays de code codePays

double tauxTVA;if (this.getCodePays()==56 || this.getCodePays()==380){// Belgique ou

tauxTVA=21; // Italie

}else {

if (this.getCodePays()==250) {// FrancetauxTVA=19.6;

}else {

if (this.getCodePays()==276) {// Allemagne

tauxTVA=19;}else {

if (this.getCodePays()==724) {// EspagnetauxTVA=18;

}else {

tauxTVA=20; // Tous les autres pays}

}}

}

return (this.getHT()*tauxTVA)/100.0;}

}

 Notez le « entre autres » dans l’énoncé. La liste des pays ne se limite pas à ceux explicités et il estdonc indispensable d’exploiter le fait que le taux est de 20% pour tous les autres pays via une imbrication

 judicieuse des if…else… Remarquez également que l’indentation (le fait de décaler le code des sous-blocs) accroit

considérablement la lisibilité. Vous pouvez demander à Eclipse d’indenter correctement le codesélectionné via le raccourci <Ctrl>+<i>. Pour indenter tout votre code code vous pouvez donc utiliser<Ctrl>+<A> (sélection de tout le code) et <Ctrl>+<i> (indentation).

Corrigé PR009  Enoncé p. 159 

Retour p. 47

Page 186: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 186/199

 

184 

Exercices de cours  Programmation Corrigés  [email protected] – B227 

/*** Classe modélisant un point du plan (2D).* @author Romuald Debruyne

*/ public class PointTab { private double[] coordonnees;/*** Initialise l'instance en la positionnant à l'origine du repère (0.0,0.0)*/

 public PointTab( ) {this.coordonnees = new double[2];this.coordonnees[0] = 0.0;this.coordonnees[1] = 0.0;

}/*** Initialise l'instance de telle sorte qu'elle ait x pour abscisse et y* pour ordonnee

* @param  x un double quelconque* @param  y un double quelconque*/

 public PointTab( double x, double y ) {this.coordonnees = new double[2];this.coordonnees[0] = x;this.coordonnees[1] = y;

}/*** Accesseur retournant l'abscisse du point* @return l'abscisse du point*/

 public double getAbscisse( ) {return this.coordonnees[0];

}/*** Accesseur retournant l'ordonnée du point* @return l'ordonnée du point*/

 public double getOrdonnee( ) {return this.coordonnees[1];

}/*** Fixe l'abscisse du point à x* @param  x un double quelconque*/

 public void  setAbscisse( double x ) {this.coordonnees[0] = x;

}/*** Fixe l'ordonnée du point à y* @param  y un double quelconque*/

 public void  setOrdonnee( double y ) {this.coordonnees[1] = y;

}// LES AUTRES METHODES SONT INCHANGEES CAR ELLES N’ACCEDENT PAS DIRECTEMENT// AUX VARIABLES D’INSTANCE}

Un point important est qu’on ne peut pas initialiser les cases du tableau  coordonnees tant que ce

tableau n’a pas été créé 

 les constructeurs commencent par créer un tableau de deux double avantd’initialiser ses cases.

Corrigé PR010  Enoncé p. 160 

Retour p. 47

Page 187: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 187/199

Exercices  de cours  Programmation Corrigés  [email protected] – B227

 

185 

a) Une première erreur concerne l’affectation d’une variable (index) qui n’a pas été déclarée.

Les autres erreurs concernent la confusion entre index et rang et l’accès potentiel à une case avec unindex trop grand. En effet, le corps de la boucle fait la conjonction avecthis.lesBooleens[index] et incrémente index de 2. C’est une stratégie valable pour balayerl’ensemble des booléens d’index pair (donc de rang impair) pour peu que (1) index soit initialisée à0 et que (2) la boucle s’arrête après qu’on ait considéré le dernier Booléen de rang impair ( il fautremplacer <= par < car en l’état on risque de sortir du tableau). Voici une version corrigée.

{ boolean conjonction = true ;int index = 0 ;while (index < this.lesBooleens.length) {

conjonction = conjonction && this.lesBooleens[ index ];

index = index + 2;}return conjonction;

}

 b) En l’état, la boucle va faire la conjonction avec les Booléens d’index 2, 6, 10, … Si on souhaitesauter un index pour passer d’index pairs en index pairs (et non sauter 3 index, ce qui nous fait louperun Booléen d’index pair) il ne faut pas à la fois incrémenter nbDejaConsideres de 2 et multiplier

 par 2 nbDejaConsideres   pour obtenir l’index du Booléen à considérer. nbDejaConsideres  nedoit être incrémenté que de 1.De plus, la condition de la boucle est également erronée. Après chaque affectation de conjonction,nbDejaConsideres est mise à jour de sorte que nbDejaConsideres  soit le nombre de Booléensd’index pair déjà pris en compte dans la conjonction. Il faut donc s’arrêter de considérer davantage deBooléens dès que nbDejaConsideres==this.lesBooleens.length  (et par conséquentremplacer <= par < dans la condition de la boucle).

{ boolean conjonction = true ;int nbDejaConsideres = 0 ;while ((nbDejaConsideres*2)< this.lesBooleens.length) {

conjonction = conjonction && this.lesBooleens[nbDejaConsideres*2 ];nbDejaConsideres = nbDejaConsideres + 1;

}

return conjonction;}

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

Corrigé PR011  Enoncé p. 161 

Retour p. 69

Page 188: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 188/199

 

186 

Exercices de cours  Programmation Corrigés  [email protected] – B227 

Ecrivez une méthode principale qui demande à l’utilisateur de saisir un entier strictement positif n au

clavier puis qui affiche la somme des entiers de 1 à n. On supposera, sans vérification, que l’utilisateursaisi bel et bien un entier strictement positif.

a) En utilisant une boucle while.

 public static void main(String[] agrs) {System.out.println("Veuillez saisir un entier strictement positif ") ;int n = Clavier.lireInt() ;int somme = 1 ;int i=2 ;while (i<=n) {

somme = somme + i;i = i + 1;

}System.out.println("La somme des entiers de 1 a "+n+" vaut "+somme) ;

 b) Sans utiliser de boucle.Il s’agit d’une simple somme arithmétique.

 public static void main(String[] agrs) {System.out.println("Veuillez saisir un entier strictement positif ") ;int n = Clavier.lireInt() ;

int somme = ((n*(n+1))/2 ;System.out.println("La somme des entiers de 1 a "+n+" vaut "+somme) ;

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

Corrigé PR012  Enoncé p. 162 

Retour p. 69

Page 189: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 189/199

Page 190: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 190/199

Page 191: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 191/199

Page 192: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 192/199

 

190 

Exercices de cours  Programmation Corrigés  [email protected] – B227 

a) En l’état, mieux vaut utiliser une boucle while car si l’ensemble est vide aucun pas de boucle n’estnécessaire.

 b) Idem a). 

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

Corrigé PR016  Enoncé p. 166 

Retour p. 73

Page 193: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 193/199

Exercices  de cours  Programmation Corrigés  [email protected] – B227

 

191 

L’entier n  est strictement positif donc la somme vaut au moins 1. On peut ici utiliser une boucledo…while si le cas du 1 est traité dans la boucle et non avant la boucle.

a) En utilisant une boucle while.

 public static void main(String[] agrs) {System.out.println("Veuillez saisir un entier strictement positif ") ;int n = Clavier.lireInt() ;int somme = 0 ;int i=1 ;do {

somme = somme + i;i = i + 1;

} while (i<=n) ;System.out.println("La somme des entiers de 1 a "+n+" vaut "+somme) ;

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

Corrigé PR017  Enoncé p. 167 

Retour p. 73

Page 194: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 194/199

 

192 

Exercices de cours  Programmation Corrigés  [email protected] – B227 

a) En utilisant l’opérateur %.

/*** @param x, un entier positif* @return true si et seulement si x est pair (false sinon)*/ 

 public static boolean estPair( int x) {return ((x%2)==0);

}

 b) Sans recourir à % mais en utilisant une boucle while.

/*** @param x, un entier positif* @return true si et seulement si x est pair (false sinon)*/ 

 public static boolean estPair( int x) {while (x>=2) {

x = x – 2;}return (x==0);

}

c) Sans recourir à % mais en utilisant une boucle do…while.

/*** @param x, un entier positif* @return true si et seulement si x est pair (false sinon)*/ 

 public static boolean estPair( int x) {do {

x = x – 2;} while (x>=2) ;return (x==0)||(x==-2);

}

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

Corrigé PR018  Enoncé p. 168 

Retour p. 73

Page 195: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 195/199

Exercices  de cours  Programmation Corrigés  [email protected] – B227

 

193 

 public class Article {

 private double montantHT; private int codePays; private  boolean tauxReduit;//true si l’article est soumis à un taux réduit

 public Article (double montantHT, int codePays, boolean tauxReduit) {this.montantHT = montantHT;this.codePays = codePays;this.tauxReduit = tauxReduit;

}

 public double getHT() {return this.montantHT;

}

 public double getTTC() {…

}}

 public class Commande { private Article[] lesArticles; private int[] quantites ;// Tableau de même taille que lesArticles

// indiquant pour chaque article la quantité commandée.…/**

* @return Retourne le montant TTC de l’ensemble de la commande

*/

 public double getTTC() {double somme=0.0;for (int i=0; i<this.lesArticles.length; i++) {

somme += this.quantites[i]*this.lesArticles[i].getTTC();}return somme;

}}

Vous pouvez vous reporter à la section Erreur ! Source du renvoi introuvable. p.

Corrigé PR019  Enoncé p. 169 

Retour p. 77

Page 196: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 196/199

Page 197: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 197/199

Exercices  de cours  Programmation Corrigés  [email protected] – B227

 

195 

a) A l’aide de conditionnelles simples.

 public class Patient {

…  public String getCorpulence() {

int imc=(int)(this.getPoids()/(this.getTaille()*this.getTaille()));if (imc<19) {

return "Mince";}else {

if (imc<22) {//et implicitement imc>=19 vu qu’on est dans la clause else  return "Normal";

}else {

if (imc<25) { // et implicitement imc>=22 return "Leger surpoids";

}else {if (imc<30) { // et implicitement imc>=25 

return "Surpoids important";}else {// l’IMC est forcement superieur ou egal à 30 

return "Obese";}

}}

}}}

 Notez que l’imbrication évite certains tests. b) A l’aide d’un branchement.

 public class Patient {… 

 public String getCorpulence() {int imc=(int)(this.getPoids()/(this.getTaille()*this.getTaille()));switch (imc) {

case 19 :case 20 :case 21 : return "Mince";case 22 :case 23 :case 24 : return "Leger surpoids";case 25 :case 26 :case 27 :case 28 :case 29 : return "Surpoids important";default : if (imc<19) {

return "Mince";}else {

return "Obese";}

}}

Corrigé PR021  Enoncé p. 171 

Retour p. 80

Page 198: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 198/199

 

196 

Exercices de cours  Programmation Corrigés  [email protected] – B227 

Ecrire la méthode nombreDeJoursDansLeMois  de la classe  Date  qui, comme son noml’indique, retourne le nombre de jours dans le mois correspondant à la date. Vous considérerez commedéjà implémentée la méthode

bissextile  retournant true  si et seulement si l’année de la date est

 bissextile.

 public class Date { private int jour, mois, annee; 

 public Date(int jour, int mois, int annee) {this.jour = jour;this. mois = mois;this. annee = annee;

} public int getJour() {

return this.jour;} public int getMois() {

return this.mois;} public int getAnnee() {

return this.annee;}

/*** @return true si et seulement si l’annee de la date est bissextile*/

 public boolean bissextile() {… 

}/*** @return le nombre de jours dans le mois de la date*/

 public int nombreDeJoursDansLeMois() {int nbJours;switch( this.getMois() ) {

case 4 :case 6 :case 9 :case 11 : nbJours=30; break;case 2 : if ( this.bissextile() ) {

nbJours=29;}else {

nbJours=28;} break;

default : nbJours = 31; break;}return nbJours;

}}

Corrigé PR022  Enoncé p. 172 

Retour p.

 80

Page 199: Programmation 2014 2015-1

8/10/2019 Programmation 2014 2015-1

http://slidepdf.com/reader/full/programmation-2014-2015-1 199/199

Exercices  de cours  Programmation Corrigés  [email protected] – B227

 

197 

Soit f(n) la fonction donnant le nombre d’opérations à coût unitaire effectuées par l’algorithme dansle pire des cas. La complexité dans le pire cas de l’algorithme est en O(n) et donc n0>0 et K>0 tels que

n>n0  |f(n)|≤Kn. Par conséquent, l’algorithme ne doit pas effectuer plus qu’un nombre fixé de foisn opérations à coût unitaire au-delà d’une certaine valeur n0. De plus, f(n) (n) ce qui signifie que

f(n) (n) puisque f(n)O(n). Par conséquent, il n’existe pas deux constantes positives K’  et n0’ telles que |f(n)|≥K’n pour tout n≥n0’. En d’autres termes, quelle que soit la valeur positive K’ qu’onchoisisse, et quelle que soit la valeur positive n0’ qu’on choisisse, il existe toujours un n≥n0’  tel que|f(n)|<K’n. Il faut donc que l’algorithme ne puisse pas avoir sa complexité dans le pire des cas

 bornée inférieurement par une fonction linéaire de n.

Plusieurs solutions existent, puisqu’il suffit que la complexité dans le pire des cas soit bornéesupérieurement par une fonction linéaire de n et ne puisse pas être bornée inférieurement par une fonctionlinéaire de n pour que l’algorithme soit solution. Voici un exemple de solution :

Si n est impair alors afficher « impair » sinon afficher l’ensemble des entiers de 1 à n.

Ce qu’on peut traduire par la procédure suivante : public static void affichageSpecial(int n) {

Corrigé PR023  Enoncé p. 173