• Aucun résultat trouvé

[PDF] Cours programmation par objets et Java | Cours java

N/A
N/A
Protected

Academic year: 2021

Partager "[PDF] Cours programmation par objets et Java | Cours java"

Copied!
153
0
0

Texte intégral

(1)Programmer avec des objets (notes provisoires, janvier 2002). Etienne Vandeput © CeFIS - FUNDP.

(2) Ces notes sont celles de la formation organisée en 2002 sur le thème précité. Elles sont donc destinées à être remaniées dans un futur proche en fonction des observations, corrections, remarques, commentaires que vous êtes invités à y apporter. Adresse de contact: etienne.vandeput@fundp.ac.be.

(3) Table des matières Chapitre 1. Pourquoi programmer avec des objets? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Le choix d’un langage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 L’installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 La machine Java virtuelle (JVM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Chapitre 2. Des objets qui dialoguent... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6. Une approche naturelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 L’encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Un exemple simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Les classes d’objets et les mécanismes de la POO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Exercice unique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Chapitre 3. Java: Notions de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11. Avertissement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Définition d’une classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 La classe Point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Les types primitifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Les méthodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Les membres de classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Les constructeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 La déclaration des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 La méthode main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 L’exécution du programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Une application qui crée des objets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Objet vs variable objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 La référence “this” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Le traitement des erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Chapitre 4. Quelques compléments utiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36. Le passage des paramètres en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.

(4) Premier point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Second point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 La classe String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 La méthode toString() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Les méthodes statiques et les variables de classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Les champs et les méthodes déclarés finals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Les opérateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Les opérateurs arithmétiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Les opérateurs logiques et de comparaison . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Les opérateurs d’incrémentation, de décrémentation et d’affectation élargie . . . . . 48 L’opérateur conditionnel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Les commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Les tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Entrées et sorties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Les conversions automatiques et le transtypage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Exercices de compréhension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Chapitre 5. Java: héritage et polymorphisme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57. Héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Spécialisation et généralisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Intérêt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Héritage, surcharge et remplacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Syntaxe en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Le modificateur d’accès “protected” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Constructeurs et héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Polymorphisme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Intérêt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Mécanisme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Chapitre 6. Les structures de contrôle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73. Utilité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.

(5) Les structures alternatives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Alternative simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Alternative multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Les structures répétitives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 La boucle “while” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 La boucle “do - while” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 La boucle “for” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 “break”, “label”, “continue” et autre “return” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Chapitre 7. D’autres mécanismes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81. Aperçu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Les classes abstraites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Les interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Héritage multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Héritage multiple et interfaces prédéfinies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Les interfaces graphiques et la gestion des événements . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Quelques outils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Le garbage collector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Les packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Déclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Les noms de packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Accès . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Hiérarchie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Stockage des classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 La recherche des classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Chapitre 8. GUI et gestion des événements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105. Le modèle des événements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 AWT et Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Que de hiérarchies! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107.

(6) Interfaces et programmation événementielle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Le détecteur de multiples de 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Première version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Deuxième version: contrôle de fermeture de la fenêtre . . . . . . . . . . . . . . . . . . . . . . 113 Troisième version: classe anaonyme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Quatrième version: autre système d’écoute et traitement des exceptions . . . . . . . . 114 Cinquième version: une mise à jour extrêmement dynamique . . . . . . . . . . . . . . . . 117 Le compteur interactif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Diagramme de classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Première version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Deuxième version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Troisième version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 Quatrième version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Les classes internes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 Chapitre 9. JavaScript, Java: quels rapports? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133. Un dilemme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Un air de famille? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Les langages de script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 Java et le HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Un brin de comparaison . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 Un autre exemple en JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Saisie de nombres et calcul d’une moyenne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Bibliographie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141.

(7) Programmer avec des objets. Chapitre 1. Etienne Vandeput ©CeFIS 2002. Pourquoi programmer avec des objets?. Introduction Il n’entre pas dans mes intentions de débattre ici des différents paradigmes de programmation et de leurs intérêts respectifs. De nombreux ouvrages et articles traitent de cette problématique. L’existence de ces paradigmes et les succès relatifs des langages qui s’en inspirent prouvent que les domaines d’application de l’informatique sont suffisamment étendus pour laisser de nombreux champs d’application possibles à chacun d’eux. Je signalerai simplement que la naissance d’un nouveau paradigme vient évidemment des limites atteintes par les langages qui sont associés aux paradigmes courants. La programmation impérative a bien répondu aux attentes, dès lors que les applications développées ne comptaient guère plus de quelques milliers de lignes et étaient le produit d’un ou deux programmeurs. Plusieurs pistes ont été et sont toujours explorées parmi lesquelles, celle de la programmation logique chère à tous ceux qui s’intéressent à l’intelligence artificielle et aux domaines dans lesquels la quantité de données à traiter est gigantesque. Mais il y a d’autres aspects. Ainsi, l’augmentation phénoménale de la complexité des logiciels fait qu’aujourd’hui, le nombre de lignes de code s’élève très souvent à des dizaines de milliers. Ce sont des équipes de programmeurs qui travaillent à la réalisation de ces logiciels et il faut éviter des pertes de temps dues à d’éventuelles synchronisation du travail. Chacun doit pouvoir travailler dans son coin en faisant confiance aux autres et en se montrant digne de la confiance des autres. En conséquence, des impératifs nouveaux apparaissent. Il devient nécessaire: • de penser les traitements d’une manière plus naturelle, plus proche de la réalité1 afin de dégager le programmeur de tout une série de contraintes opérationnelles; • d’encapsuler les traitements dans des modules qui soient des boîtes noires équipées d’une interface, permettant au programmeur de les utiliser sans savoir comment ces traitements sont implantés, mais connaissant les éventuelles données à fournir et les éventuels résultats retournés; • d’évoluer ainsi vers un développement qui favorise la réutilisation logicielle et l’adaptabilité. C’est essentiellement de ces nécessités qu’est née la programmation orientée objet. Cela explique notamment que ce n’est pas un programme d’addition de nombres saisis au clavier jusqu’à ce qu’un signal soit donné (valeur spéciale ou bidon) qui vous convaincra du bien-fondé de ce type de programmation et cela, même si un tel programme peut être écrit au moyen d’objets.. 1. Dans certains cas, un raisonnement déterministe n’est pas toujours celui qui est le plus approprié.. Chapitre 1 Pourquoi programmer avec des objets?. -1-.

(8) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. Quant à la programmation impérative, elle a encore de beaux jours devant elle, ne fusse que par la nécessité de maintenir une quantité de programmes utiles et qui fonctionnent2. Le but de ce cours n’est pas de vous convaincre que la programmation orientée objet3 est la solution à tous les problèmes, mais seulement de vous faire percevoir quels en sont les mécanismes fondateurs afin de vous permettre de juger, dans quelles situations celle-ci se révèle intéressante. Toutes ces choses étant dites, il faudra sans doute perdre un peu de vos habitudes de programmation pour bien cerner tout le profit que vous pourrez tirer de cette autre manière de programmer. L’introduction qui sera faite et les exemples qui seront choisis tenteront de vous faire oublier vos anciennes amours et de vous attirer hors de leur champ d’influence. Ce cours a aussi pour objectif d’analyser dans quelle mesure les concepts qui y sont développés sont accessibles à des élèves du degré supérieur de l’enseignement secondaire. Vos avis seront donc très autorisés en la matière. Les notions seront présentées de la manière la plus pédagogique possible 4 de manière à pouvoir en juger efficacement.. Le choix d’un langage Une dernière chose enfin, il n’est pas possible de parler langage de programmation sans en choisir un en particulier. Ceux qui ont suivi des cours sur la programmation impérative ont souvent utilisé le langage Pascal pour développer des applications. Beaucoup d’experts du domaine de l’enseignement estimaient, sans doute à raison, que ce langage était pédagogique, même s’il n’offrait pas les facilités de développement de certains autres langages. Nous utiliserons principalement le langage Java, même si je caresse l’espoir de pouvoir faire une petite incursion du côté d’un langage de script (en l’occurrence, Javascript). En voici, de mon point de vue et par ordre décroissant d’importance à mes yeux, les principales raisons: • Java est un langage de programmation qui met en oeuvre assez clairement les mécanismes fondamentaux de la programmation orientée objet que sont l’héritage, la surcharge et le polymorphisme;. 2. Une entreprise se moque pas mal de faire réécrire des programmes qui fonctionnent bien dans de nouveaux langages, dans la mesure où la réécriture est une source de problèmes potentiels.. 3. La Programmation Orientée Objet (POO) se caractérise par l’utilisation d’un certain nombre de mécanismes liés à la création des objets. La plupart des langages de programmation se revendiquant de cette catégorie ne peuvent cependant gommer totalement tous les aspects de la programmation impérative. C’est en ce sens qu’on parle de programmation orientée objet. Certains langages permettent de les réduire à la portion congrue en exploitant au maximum les mécanismes de la POO, d’autres continuent à nécessiter une part importante de programmation impérative tout en proposant certains des mécanismes en question. On parlera donc de langages complètement orientés objet pour désigner les premiers et de langages orientés objet pour désigner les autres et cela, quel que soit leur degré de respect des mécanismes de la POO.. 4. C’est en tous cas ma volonté.. Chapitre 1 Pourquoi programmer avec des objets?. -2-.

(9) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. • Java demande de la rigueur dans la structure et l’écriture des programmes et les implicites y sont moins nombreux que chez la plupart des langages de script (Javascript, Perl, Php, Python,...); • Java a grandi avec le Web, ce qui le rend bien adapté à son exploitation; • un programme écrit en Java et compilé en octets de code peut tourner sur n’importe quel type de matériel et n’importe quel type de plateforme. Finalement, les huit cours qui sont prévus s’avèreront insuffisants pour couvrir un aperçu assez large de ce que propose Java. Sans connaître ni les capacités du groupe, ni le temps qu’il me faudra pour mettre en place les fondements du langage, j’opterai pour l’installation solide des concepts, même si ce choix m’oblige à envisager avec vous une suite au cours de l’année académique prochaine. C’est une évidence mais laissez-moi vous redire que la bonne compréhension d’un tel cours passe par une pratique minimum. Entre les différentes séances, je ne puis que vous encourager à programmer les petites applications que je vous proposerai.. L’installation Cette section est un peu plus technique mais il faut bien décrire quelque part, comment acquérir une version du langage Java et comment l’installer. Je vous suggère d’installer Java2 SDK (Software Development Kit) version 1.3. Cette version est actuellement appelée Java2 Platform Standard Edition v. 1.3. Vous le trouverez à la source c’est-àdire à l’adresse http://java.sun.com/j2se/1.3/ et cela, que votre OS préféré soit Windows, Linux ou même Solaris. Un exécutable d’environ 40 Mo est à télécharger. Son exécution installe le langage et toute la hiérarchie des librairies dont il a besoin. Sous Windows, le dossier par défaut est c:\jdk1.3.1_02 mais il est possible de faire un autre choix de dossier5.. 5. Il existe une autre solution: installer Jbuilder 5 Personal un produit de Borland qui offre d’excellentes possibilités d’édition de programmes en Java. Ce logiciel contient une version du JDK 1.3 (Java Development Kit). Cette version est gratuite pour autant que vous respectiez le contrat de licence qui vous est proposé. Elle est téléchargeable à partir de l’adresse http://www.borland.com/jbuilder/. Le fichier compressé à télécharger est de 40 Mo pour la version Windows et de 53 Mo pour la version Linux. Bien entendu, il est tout à fait possible de rédiger du code Java en utilisant le simple blocnotes de Windows ou un éditeur de texte élémentaire. Un produit comme Jbuilder fournit aux développeurs des tas de services intéressants allant de la coloration syntaxique à la génération de documentation de programme en passant par l’indentation automatique, une gestion souple des fichiers etc. La relative convivialité du produit parle en la faveur de son auto-découverte car soyons clairs, la connaissance d’un tel outil dédié aux développeurs professionnels n’est pas l’objectif du cours. Son étude nous éloignerait d’ailleurs de l’essentiel. A vous de voir si l’installation de Jbuilder, à terme, vous sera utile. Tenez compte également des performances de votre matériel.. Chapitre 1 Pourquoi programmer avec des objets?. -3-.

(10) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. La machine Java virtuelle (JVM) La description qui suit n’est pas nécessaire à la compréhension du prochain chapitre. Sa lecture peut être différée. Cependant, on évoque tellement souvent la machine virtuelle qu’il me semble utile d’en donner une explication à ce stade à l’intention de ceux qui connaissent déjà un peu les tenants et aboutissants de la programmation orientée objet. Une des préoccupations qui se fait jour au moment du développement du projet Java, c’est la portabilité des applications sur différentes plate-formes. C’est une exigence qui naît du développement d’Internet mais aussi de l’évolution de l’architecture informatique de nombreuses grosses entreprises, de systèmes centralisés vers des systèmes distribués. La variété du matériel et des systèmes d’exploitation en interconnexion impose que les applications développées dans des langages modernes puissent être hébergées sur des systèmes très hétéroclites. Comment cette caractéristique de portabilité est-elle obtenue? Que représente cette machine virtuelle qu’on évoque pour expliquer cette qualité du langage. En voici une très brève explication. L’installation de Java dont il vient d’être question consiste notamment en la fourniture : • d’un grand nombre de classes prédéfinies • de plusieurs outils indispensables (compilateur, interpréteur, générateur de documentation, débogueur,...) Pourquoi un compilateur et un interpréteur? Le principe est le suivant: sur un système donné, le compilateur transforme le code source (texte des programmes) en “octets de code” (bytecodes en anglais). Il s’agit d’un langage universel que chacun des systèmes s’engage à déchiffrer au moyen de son interpréteur spécifique capable de digérer ces octets de code en tenant compte du contexte local. Les bytecodes générés par la machine A gouvernée par l’OS A’ peuvent maintenant être interprétés par l’interpréteur de la machine B gouvernée par l’OS B’. En d’autres termes, un même programme, compilé par différents systèmes, fournit les mêmes bytecodes. A l’exécution du programme sur un système donné, ces bytecodes sont interprétés grâce à un interpréteur propre au système. Le couple constitué de ce système donné et d’une instance de l’interpréteur est appelé machine virtuelle. Un même système peut donc être à la base de l’existence de plusieurs machines virtuelles6. Nous verrons par la suite que pour qu’un programme puisse être exécuté, il faut qu’existe une classe exécutable. Elle doit être enregistrée dans un fichier qui porte le même nom qu’elle suivi de l’extension java. Si la classe exécutable s’appelle Application, elle doit être enregistrée dans un fichier qui s’appelle Application.java.. 6. Cette opportunité nous sera de peu d’utilité tant que nous ne développons pas des applications qui interagissent entre elles.. Chapitre 1 Pourquoi programmer avec des objets?. -4-.

(11) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. Le code contenu dans ce fichier (et dans les fichiers qui lui sont liés7) est compilé grâce à la commande javac suivie du nom du fichier. La commande javac correspond donc à l’activation de l’outil de compilation. Le fichier résultant portera le nom de la classe suivi cette fois de l’extension class. La compilation du fichier Application.java se fait par la commande javac Application.java et produit un fichier Application.class.. Le code de cette classe est exécuté en utilisant la commande java suivi du nom de ce dernier fichier, sans l’extension. Elle correspond à l’activation de l’interpréteur de bytecodes. La commande java Application produit l’exécution du programme 8.. Toutes les commandes qui viennent d’être évoquées sont données au niveau d’un shell de commandes du système d’exploitation utilisé et fonctionnent sous réserve d’un choix correct des paramètres concernant les variables d’environnement (notamment les chemins que l’OS doit suivre pour trouver les programmes et ceux que les programmes doivent suivre pour trouver le code des applications).. 7. Il est clair que la définition d’une classe, y compris celle d’une classe exécutable, fait généralement appel à d’autres définitions de classes contenues dans d’autres fichiers. La compilation consiste à générer des bytecodes qui intègrent les informations contenues dans ces différents fichiers.. 8. Cette commande peut comporter d’autres paramètres. En particulier, nous verrons qu’il est possible, et même souhaitable, de définir dans les différentes commandes les chemins d’accès aux fichiers. Pour ce qui est du lancement d’une JVM, on peut aussi fournir des paramètres qui sont récupérables par le programme.. Chapitre 1 Pourquoi programmer avec des objets?. -5-.

(12) Programmer avec des objets. Chapitre 2. Etienne Vandeput ©CeFIS 2002. Des objets qui dialoguent.... Une approche naturelle Un des reproches que l’on peut faire à la programmation impérative est d’éloigner le programmeur du monde réel en l’obligeant à décrire, d’une manière très élémentaire, des actions et des traitements qui sont parfois très complexes. Les limites de ce type de démarche sont atteintes dès l’instant où l’ensemble de ces instructions devient pléthorique. Il devient alors difficile de contrôler l’ensemble des modules d’une application, même lorsque l’analyse de celle-ci a fait l’objet d’une approche descendante. Une autre critique importante revient régulièrement lorsqu’on parle de programmation impérative: l’application programmée répond généralement à une vision, espérons-le correcte, que l’on a des traitements au moment du développement de celle-ci. La conséquence, c’est que les programmes rédigés manquent souvent d’adaptabilité et que le monde est (trop) souvent à refaire. La programmation orientée objet trouve une partie de son intérêt dans la réponse qu’elle apporte à la difficulté qui vient d’être évoquée. Pour prendre un exemple simple, un patron ne peut gérer une très grosse entreprise en voulant s’occuper des moindres détails de son fonctionnement, des grandes décisions stratégiques, jusqu’à l’achat des produits d’entretien des locaux, en passant par la paie des ouvriers, par exemple. Il doit pouvoir faire confiance à ses subordonnés et se limiter à une interaction avec eux. C’est un peu l’idée de la programmation orientée objet d’arriver à constituer des logiciels basés sur l’interaction entre les objets, chacun pouvant demander à d’autres d’effectuer certaines tâches pour la réalisation desquelles eux-mêmes s’adresseront à d’autres objets et ainsi de suite. Un des principes sur lesquels nous reviendrons est basé sur le fait qu’une relation de confiance existe entre les objets. Chacun d’entre eux propose et s’engage à rendre au monde extérieur (les autres objets potentiels) un ensemble de services. Il le fait via une interface d’interaction qui ne permet pas de savoir comment ces services sont rendus. Le déroulement d’une application ressemblera à une conversation entre objets9. Ceux-ci vont donc s’envoyer mutuellement des messages qui seront autant de demandes de sous-traitance. Si un objet ne peut réaliser une partie du travail qui lui est demandé, il devra pouvoir confier cette partie du travail à un autre objet. La conversation entre objets sera donc aussi constituée de réponses que les objets s’enverront les uns les autres. Pour établir une comparaison avec des choses connues, une demande de service d’un objet à un autre est une sorte d’appel de fonction. Dans le vocabulaire de la POO, on parlera d’appel de méthodes.. L’encapsulation. 9. Il faudra bien qu’un objet engage la conversation!. Chapitre 2 Des objets qui dialoguent.... -6-.

(13) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. C’est un des principes essentiels de la POO. Un objet est caractérisé par son comportement et par son état. Son comportement est décrit par les services qu’il peut rendre et donc, d’une certaine manière par les fonctions qu’il peut remplir. Nous avons déjà signalé qu’on parlait ici de méthodes plutôt que de fonctions. L’état d’un objet est ce qui le caractérise à un moment donné. Cet état est variable, dépend de ses comportements et des comportements des autres objets. La structure d’un objet ne lui est généralement pas propre. Il fait partie d’une classe d’objets qui la partagent. Il en est ainsi dans le monde réel. Une personne, une voiture, un chien, une carte d’identité,... possèdent généralement une série de propriétés communes, même si les valeurs qui y sont attachées sont différentes. Les personnes n’ont pas le même nom, les chiens ne sont pas de la même race, les cartes d’identité ne contiennent pas la même photo,... Ils ont également une série de comportements identiques. Les personnes parlent, les chiens aboient, les voitures peuvent freiner et accélérer,... Il n’est pas du tout souhaitable que chaque objet puisse modifier anarchiquement et directement l’état des autres objets. Il est préférable de réserver la modification de l’état à l’objet lui-même. Ceci n’implique pas qu’un objet puisse demander cette modification mais il devra le demander à l’objet lui-même qui pourra, notamment, s’assurer que cette modification est valide. Il vaut mieux, en effet, qu’un seul objet prenne cette responsabilité en charge. Ces remarques vont nous conduire à définir, plus tard, la portée des variables et des méthodes. Si le comportement d’un objet est caractérisé par les méthodes qu’il supporte, son état est principalement décrit par des variables propres appelées variables d’instances. Pour désigner cette association de l’état d’un objet à son comportement, on parle d’encapsulation. Les données et les traitements ne semblent plus séparés mais donnent l’impression d’être regroupés à l’intérieur de l’objet lui-même. L’encapsulation présente un avantage incontestable. Lorsqu’un programmeur utilise des classes qu’il n’a pas développées lui-même et en crée des instances, il ne connaît pas la manière dont les traitements correspondant à l’exécution des méthodes sont implantés. La seule chose que celui-ci connaisse, c’est l’ensemble des services rendus par la classe, le contrat qu’elle s’engage à remplir en quelque sorte 10 . Cet avantage n’est pas à négliger lorsqu’il s’agit d’évoluer vers un type de programmation dont une partie importante de la démarche consiste à réutiliser des modules (logiciels) existants. Un exemple simple Considérons un carré. On peut imaginer que son état soit décrit par deux données variables que sont la longueur de son côté et la coordonnée dans un repère défini de son coin supérieur gauche . Le fait d’évoquer un carré contient implicitement la référence à un objet de la classe des carrés. On peut demander beaucoup de services à un objet de type carré. Les plus évidents sont sans doute: • calculer et fournir son périmètre, 10. Dans le contexte d’une bonne programmation, les classes sont généralement bien documentées, qu’il s’agisse de décrire le contrat rempli par chacune des méthodes ou de détailler la nature des autres membres de la classe.. Chapitre 2 Des objets qui dialoguent.... -7-.

(14) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. • calculer et fournir son aire, • se dessiner, • changer ses propres dimensions ou sa position, • fournir certains de ces renseignements à la demande, • ...11 Lorsqu’on demandera à un objet carré de changer la valeur de la longueur de son côté, celui-ci pourra vérifier que la valeur fournie est cohérente et faire en sorte de corriger les éventuelles erreurs pour que les données soient consistantes. Par exemple, si le paramètre fourni pour la longueur du côté est négatif, l’objet pourra décider de lui donner la valeur 0. Le fait de confier cette tâche à l’objet lui-même combiné au fait que l’accès aux données peut lui être réservé, empêche tout objet (logiciel12) extérieur de rendre le système de données inconsistant.. Les classes d’objets et les mécanismes de la POO En programmation orientée objet, chaque objet fait partie d’une classe dont la description mentionne les données et le comportement qui le caractérisent ainsi que ses semblables. En suivant l’exemple, la description de la classe des carrés mentionnera l’existence de deux champs de données: la longueur du côté et la position du sommet supérieur gauche. Elle précisera les méthodes disponibles, celle qui calcule et affiche le périmètre, celle qui modifie la position du sommet,... en indiquant chaque fois le nombre et le type des paramètres à fournir. Un programmeur qui utilisera la classe carré saura qu’il peut en obtenir le périmètre sans savoir comment le calcul est effectué13. Le mot “type” est bien connu des programmeurs. La programmation orientée objet fera généralement apparaître deux sortes de types: les types primitifs (entiers, caractères, booléens,...) et les types construits (ceux qui correspondent aux classes d’objets). Ainsi, un objet peut être déclaré de type carré, cela signifiera qu’il est caractérisé par tel et tel types de données et par telle et telle méthodes. Notre exemple peut constituer une application directe de ce qui précède. Nous pouvons décider que le type de donnée pour la longueur du côté est “nombre entier” qui est un type primitif et que le type de donnée pour le sommet est point ou point constitue une autre classe d’objets.. 11. Dans une perspective graphique plus poussée, on pourrait considérer que le carré possède un fond coloré, un bord ayant lui-même une épaisseur et une couleur, etc.. 12. De par le fait qu’un objet encapsule ses données et ses méthodes, on assimile parfois le mot “objet” au mot “logiciel”. Certains objets peuvent en effet être d’une grande complexité.. 13. Dans ce cas-ci, ça peut paraître évident. Notez toutefois que le calcul pourrait consister à faire multiplier l’aire du carré par 16 et prendre la racine carrée du résultat. La seule chose qui intéresse l’utilisateur (programmeur) c’est la garantie d’obtenir la valeur du périmètre.. Chapitre 2 Des objets qui dialoguent.... -8-.

(15) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. Toutes ces possibilités prendront forme dans le chapitre suivant consacré à Java. En attendant, et pour montrer que la programmation orientée objet fait la part belle à l’abstraction, nous pourrions encore avoir une autre vue des choses et décider de créer d’abord une classe point qui contiendrait, par exemple, deux données de type nombre entier (une abscisse et une ordonnée). Nous choisirions alors de dériver la classe carré de la classe point en précisant qu’un carré, c’est d’abord un point (son sommet supérieur gauche) avec en plus, la longueur d’un côté (ce qui permettrait de le définir complètement)14. Ceci permet d’amorcer la présentation d’un des mécanismes classiques de la POO à savoir l’héritage. L’héritage est ce que l’on a inventé de mieux pour justement ne pas devoir tout réinventer. En se basant sur le principe qui veut que ce qui a déjà été défini peut être réutilisé ou légèrement modifié et que le reste peut être ajouté, une classe d’objets peut hériter d’une autre classe en la spécialisant. Cette spécialisation consiste: • à rajouter des choses qui n’existaient pas dans la définition de la classe précédente, à savoir des champs de données ou des méthodes; • à redéfinir certaines méthodes en leur faisant faire les choses de manière différente, tout en se ménageant la possibilité de considérer l’objet comme faisant aussi partie de la classe d’héritage. On peut aussi envisager les choses d’une autre manière en considérant que des objets appartenant à des classes différentes ont des points communs qui pourraient permettre de les considérer comme faisant tous partie d’une classe d’objets plus générale. L’héritage s’examinera donc souvent dans le sens de la spécialisation mais parfois aussi dans celui de la généralisation. Cette petite réflexion nous permet aussi d’amorcer la description d’un autre mécanisme fondamental: le polymorphisme. Si la classe d’un objet hérite d’une autre classe, tout objet de la première est aussi un objet de la seconde15. De ce fait, l’objet a plusieurs formes possibles et on peut donc l’invoquer en le considérant de différentes manières. C’est pourquoi on parle de polymorphisme. Il existe en POO d’autres mécanismes tels, par exemple, la surcharge. Un résultat peut être renvoyé par une méthode sur base de données différentes. Ainsi, le calcul de l’aire du carré peut être réalisé sur base de la connaissance de la longueur du côté de celui-ci, mais aussi, pourquoi pas, sur base de la connaissance des coordonnées de deux sommets opposés. Dans le premier cas, l’unique paramètre est un simple entier alors que dans le second, les deux paramètres sont des objets “points”. Pour qu’un compilateur puisse identifier une méthode sans équivoque, il se réfère à sa signature qui comprend nécessairement le nom de la méthode mais aussi la liste (éventuellement vide) des paramètres et de leurs. 14. Ceci a (peut-être) de quoi faire dresser les cheveux sur la tête des mathématiciens. Dire qu’un carré est une sorte de point est en effet assez osé. Le mathématicien dirait plutôt qu’un point correspond à un carré dont la longueur du côté est nulle... et encore. Pourtant, cette manière de voir les choses peut être commode en POO.. 15. Attention, l’inverse n’est pas vrai car la classe qui hérite “spécialise” la classe d’héritage. Il est fort probable, par exemple, qu’elle supporte des méthodes que la précédente ignore.. Chapitre 2 Des objets qui dialoguent.... -9-.

(16) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. types. C’est en ce sens qu’on parle de surcharge de la méthode. On peut donc dire qu’un même nom de méthode dissimule des sémantiques différentes16. Nous avons évoqué le mécanisme d’héritage. Beaucoup de langages de POO implantent un mécanisme d’héritage multiple. Une classe peut hériter de plusieurs autres classes au sens où nous l’avons défini. La sous-classe hérite alors de caractéristiques de toutes les classes dont elle hérite. Cela ne va pas sans poser un certain nombre de problèmes17. Cette première approche devrait suffire à comprendre dans quel esprit fonctionne la POO. L’algorithmique reste bien présente, notamment au niveau de la description des méthodes. Néanmoins, tout code préalablement rédigé et qui fonctionne, c’est-à-dire qui remplit son contrat, ne doit plus être pris en compte par celui qui utilise l’objet. Cette approche autorise, vous l’aurez compris, un meilleur débogage et une meilleure localisation des problèmes. Dans le chapitre suivant, nous vous proposons de découvrir comment Java, un langage qualifié de totalement orienté objet, implante les concepts qui viennent d’être décrits. Ce sera aussi l’occasion de découvrir la syntaxe de ce langage et de souligner quelques bonnes habitudes rédactionnelles. A la fin du syllabus, nous tentons une comparaison, si tant est qu’elle ait du sens, entre Java et JavaScript que l’on pourrait qualifier de faiblement orienté objet.. Exercice unique En vous basant sur l’exemple du carré dont les sommets sont des points qui ont chacun une coordonnée, identifiez, dans les domaines que vous connaissez, des objets dont la définition fait éventuellement appel à d’autres objets. Imaginez, pour ces objets et ceux qui les composent, des méthodes que l’on pourrait invoquer auprès d’eux en précisant ce que ces méthodes sont sensées effectuer comme traitement ou renvoyer comme résultat. Pour que les choses soient claires, voici d’autres orientations possibles pour étoffer l’exemple du carré et des points18. Elles seront traitées dans les chapitres qui suivent. Vous devriez pouvoir tenir un discours comme celui qui suit, discours qui vous permettrait de dégager les classes, les champs de. 16. Dans notre exemple, le résultat renvoyé est un entier qui représente l’aire du carré mais rien n’empêche que la sémantique même des résultats soient tout à fait différentes selon le nombre et le type des paramètres de la méthode.. 17. Le langage Java, que nous étudierons au prochain chapitre, n’implante pas directement la notion d’héritage multiple. Une classe ne peut hériter que d’une seule autre classe. Néanmoins, le concept d’interface autorise sa simulation en en supprimant les désavantages.. 18. Pardonnez-moi d’avoir puisé cet exemple dans le domaine des mathématiques, ma première vocation ;-). Chapitre 2 Des objets qui dialoguent.... - 10 -.

(17) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. données et leurs types (donc éventuellement d’autres objets) ainsi que quelques méthodes supportées par ces classes d’objets19. Une droite est constituée de points. Deux points permettent de définir une droite, mais il y peut y avoir d’autres moyens. On peut demander à une droite de changer de direction, de glisser parallèlement à elle-même. Pour autant que l’on ait défini ce qu’est un cercle, on peut demander à une droite si elle est tangente à un cercle donné, si elle comprend un point donné etc. De la description qui précède, on peut retenir qu’à tout le moins, il existe des points, des droites et des cercles. Pour ce qui est des droites, on peut imaginer une méthode qui répondra par vrai ou faux à la question: comprends-tu tel point? Il s’agira d’un résultat. Une autre méthode ne fournira pas de résultat mais modifiera les paramètres de la droite lorsqu’on lui demandera de glisser parallèlement à elle-même pour passer par un point donné etc.. 19. Il serait utile que chacun s’impose une telle description de manière à pouvoir la faire partager lors de la prochaine séance. Cette réflexion pourrait conduire à la constitution d’une mini-base de données d’exemples exploitables en situation d’enseignement.. Chapitre 2 Des objets qui dialoguent.... - 11 -.

(18) Programmer avec des objets. Chapitre 3. Etienne Vandeput ©CeFIS 2002. Java: Notions de base. Avertissement Dans ce chapitre, j’éviterai, autant que possible, de vous noyer dans une multitude de détails, même si ceux-ci sont importants. Je me contenterai de préciser les éléments qui vous permettront assez rapidement de réaliser une petite application Java en mettant d’emblée l’accent sur les concepts qui me paraissent fondamentaux. A ce stade, il n’est pas encore question de mettre en oeuvre les mécanismes principaux de la POO. Nous sommes évidemment encore bien loin de pouvoir nous intéresser à la manière de conduire le développement d’une application. . Il y a tellement de choses à illustrer que nous laisserons un peu de côté (pour l’instant) la méthodologie.. Définition d’une classe Pour une introduction en douceur de la syntaxe Java, intéressons-nous aux classes que nous avons évoquées dans le chapitre précédent 20. Définissons-les en apportant à leur définition les commentaires utiles. La classe Point Pour rappel, cette classe caractérise des objets Point qui ont une coordonnée composée d’une abscisse et d’une ordonnée. Nous décidons que ces deux informations sont des nombres entiers. Voici à quoi pourrait ressembler la définition de cette classe. class Point{ public int x; public int y; }. 20. Je me permets d’en rajouter encore un peu à l’avertissement, en vous faisant remarquer que les objets dont il est ici question ne s’inscrivent pas dans une problématique bien précise. Il faut d’ailleurs reconnaître qu’un des intérêts de la POO, c’est de pouvoir revisiter la définition des objets en fonction de nécessités nouvelles. On définira donc souvent des classes d’objets de manière très schématique, voire très courte, simplement parce qu’on les a identifiées en réservant à plus tard une description plus détaillée. Le fait que certaines classes d’objets ne soient pas utilisées “in fine” n’est pas vraiment un problème.. Chapitre 3 Java: notions de base. - 12 -.

(19) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. Dans la définition d’une classe, le mot-clé class est suivi du nom de la classe. Le nom d’une classe doit impérativement commencer par une lettre et peut se poursuivre par des chiffres et des lettres. En Java, on utilise conventionnellement des noms de classes commençant par une lettre majuscule et on utilise des lettres majuscules au début de chaque autre mot dans le nom: Formes, FormesGeometriques, CompteurDeMots,... Attention, Java est sensible à la casse. Tout ce que la classe englobe en termes de champs de données et de méthodes est encadré par des accolades. Une bonne habitude de rédaction consiste à faire suivre le nom de la classe de l’accolade ouvrante et de placer l’accolade fermante au même niveau que le premier caractère de la ligne de définition de la classe, ce qui permet une détection rapide des erreurs de syntaxe dues à leur absence. Comme dans de nombreux langages, le séparateur d’instruction en Java est le point-virgule. Le mot public utilisé pour les champs de données, mais qui peut l’être aussi pour la classe et les méthodes, est un modificateur d’accès. Nous discuterons plus tard de l’opportunité d’élargir ou de restreindre les accès aux champs de données et aux méthodes. Les objets de cette classe comptent deux champs de données qui sont du type primitif “entier” (int) et ne supportent, pour l’instant, aucune méthode.. Les types primitifs Java est un langage fortement typé. Le type de chacune des variables doit être impérativement précisé. Un rapide premier contact avec ces types primitifs nous apprend qu’ils sont au nombre de huit: • quatre types entiers; • deux types réels à virgule flottante; • un type caractère; • un type booléen. Le type int est codé sur 4 octets, le type short sur 2 octets, le type long sur 8 octets et le type byte sur un seul. Le type float est codé sur 4 octets et le type double sur 8 octets21. Le type char correspond à l’Unicode (2 octets)22. Le type boolean prend les valeurs true et false. Les méthodes Nous allons pallier l’absence de méthodes de la classe point en créant une méthode qui fournit la valeur de l’abscisse du point, une qui fournit son ordonnée et deux autres méthodes qui permettent de les modifier. Ces méthodes sont donc autant de services que l’objet peut rendre au monde extérieur.. 21. Java utilise la norme IEEE 754-1985.. 22. Attention, syntaxiquement ‘A’ désigne le caractère A alors que “A” désigne la chaîne de caractères A. Il n’y a pas de type primitif pour les chaînes de caractères mais il existe une classe String prédéfinie.. Chapitre 3 Java: notions de base. - 13 -.

(20) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. class Point{ private int x; private int y; public int getAbscisse(){ return x; } public int getOrdonnee(){ return y; } public void setAbscisse(int a){ x=a; } public void setOrdonnee(int b){ y=b; } }. La définition d’une méthode commence généralement par un modificateur d’accès. Elle comprend également le type de résultat renvoyé par la méthode s’il y en a un. Les méthodes getAbscisse et getOrdonnee renvoient un résultat dont le type est le type primitif “entier”. En cas d’absence de résultat retourné, le mot clé est void comme dans les méthodes setAbscisse et setOrdonnee. Le choix du nom de la méthode est soumis à la recommandation suivante: lettres minuscules (et éventuellement chiffres) et majuscule à la première lettre de chaque mot à partir du deuxième. Le nom de la méthode est suivi des paramètres éventuels précédés de leur type et séparés par des virgules23. L’opérateur d’affectation est symbolisé par le signe =. Lorsqu’il s’agit d’affectation entre objets, ce sont des références qui sont unifiées. Voyez à ce propos ce qui est dit de la construction des objets.. Le choix d’un accès public pour les méthodes est assez classique. Les objets extérieurs doivent pouvoir invoquer la méthode de l’objet sauf si celle-ci est destinée à l’usage exclusif de la classe. Dans ce cas, il vaut mieux la déclarer private. L’accès aux champs de données est maintenant private 24. C’est une bonne idée que d’empêcher la modification de l’état de l’objet par d’autres objets que lui-même. En d’autres termes, plutôt que de 23. Lorsque le paramètre est un objet, le type n’est pas un type primitif, mais la classe à laquelle l’objet est censé appartenir.. 24. Il est bon de donner aux champs d’une classe l’accès le plus restreint possible et à l’élargir en fonction des nécessités. Dans le tout premier exemple, la classe Point ne comprenait pas de méthode. Il était donc impératif que les champs soient déclarés public.. Chapitre 3 Java: notions de base. - 14 -.

(21) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. modifier l’état d’un autre objet, un objet invoquera la méthode de ce dernier pour accomplir le travail. L’intégrité des données est ainsi plus facile à assurer de même que le débogage et la maintenance. On sent que l’idée sous-jacente est de créer du logiciel qui soit facile à adapter, grâce à une localisation précise des endroits où les traitements sont effectués. Les membres de classes Les méthodes et les champs de données sont appelés membres de classe. Une classe peut aussi posséder, comme membres, d’autres classes (ou des interfaces25) mais cela ne nous est pas très utile pour l’instant. Le type d’accès à chaque membre de classe doit être spécifié. Jusqu’à présent, nous avons évoqués les accès public et private mais l’accès protected pourra aussi nous intéresser par la suite. Les constructeurs Un programme OO a pour objectif essentiel de faire naître des objets dans le but de les faire communiquer et réagir. Pour prendre un exemple très élémentaire, lorsqu’un objet carré est créé, un autre objet peut en invoquer les méthodes afin d’obtenir des informations à son sujet (son aire, son périmètre,...). Cela signifie qu’il est nécessaire de disposer d’une technique de construction des objets. A cette fin, chaque classe doit contenir au moins un constructeur d’objets 26. Le constructeur d’objets est une sorte de méthode de fabrication de l’objet bien qu’il ne s’agisse pas d’une méthode au sens défini précédemment. Il existe un constructeur par défaut qui ne comporte évidemment aucun paramètre. Le programmeur a le loisir de définir autant de constructeurs qu’il le souhaite. Ceux-ci vont différer par les paramètres qu’ils vont accepter et par les initialisations des objets qu’ils vont effectuer. Nous savions déjà que la définition d’une classe se composait de la définition des champs de données et de celle des méthodes de la classe. Nous pouvons maintenant y ajouter les constructeurs des objets (autres que le constructeur par défaut qui ne doit pas être défini). Un constructeur d’objets d’une classe porte toujours le nom de la classe. Sa signature27 peut comporter de 0 à n paramètres. Comment, concrètement, un objet est-il créé? Le jeu de la communication des objets entre eux fait qu’à un moment donné du déroulement du programme, une méthode d’une des classes d’objets est en train de s’exécuter. Il est possible que cette exécution résulte elle-même d’un appel provoqué par l’exécution d’une autre méthode associée à un autre objet ou à une autre classe. La création d’un objet est une des instructions possibles faisant partie du code de la méthode exécutée. La manière dont l’objet est créé (l’instruction) détermine celui des constructeurs qui doit être choisi.. 25. La notion d’interface est la réponse de Java à l’absence de mécanisme d’héritage multiple. Cette notion est développée plus loin.. 26. A titre d’exception, nous verrons qu’il existe des classes qui ne sont jamais instanciées.. 27. La signature d’une méthode ou d’un constructeur comprend son nom, la liste des paramètres et leur type.. Chapitre 3 Java: notions de base. - 15 -.

(22) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. Améliorons la classe Point en y ajoutant deux constructeurs. public class Point{ private int x; private int y; public Point(){ setPoint(0,0); } public Point(int a,int b){ setPoint(a,b); } public int getAbscisse(){ return x; } public int getOrdonnee(){ return y; } public void setAbscisse(int a){ x=a; } public void setOrdonnee(int b){ y=b; } public void setPoint(int a,int b){ x=a; y=b; } }. Le premier constructeur est sans paramètre. Son utilisation provoque la création d’un point origine. Le second constructeur demande deux paramètres de type entier. Syntaxiquement, la création d’un point prendra une de ces formes: Point p1=new Point(); Point p2=new Point(3,5); ou une forme équivalente comme Point p1; int a=4; .... Chapitre 3 Java: notions de base. - 16 -.

(23) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. p1=new Point(4,a) Une bonne habitude consiste à choisir comme identificateurs de variables des chaînes de caractères contenant des lettres et éventuellement des chiffres en utilisant la même règle que pour les méthodes (lettres minuscules et première lettre en majuscule à partir du deuxième mot; exemple: centreDuCercle). Notez aussi que les types primitifs commencent par une minuscule ce qui permet de les distinguer des types correspondant aux classes d’objets.. Dans la description de la classe, nous avons rajouté une méthode setPoint qui permet de modifier à la fois l’abscisse et l’ordonnée d’un point. Cette méthode apparaît dans la définition des deux constructeurs. Les constructeurs sont déclarés d’accès public ce qui permet à des méthodes d’autres classes d’invoquer la création de nouveaux objets. Chaque fois qu’un objet est créé, on dit que la classe est instanciée. Les variables que constituent les champs de données d’un objet sont propres à chacun d’eux, malgré qu’elles portent les mêmes noms. C’est la raison pour laquelle on parle de variables d’instances pour les désigner. S’il n’y a pas d’ambiguïté (objet courant), la variable d’instance est désignée par son nom. Dans le cas contraire, le nom de l’objet doit être mentionné suivi d’un point et du nom de la variable. L’instruction abscisse = p1.ordonnee; signifie que la valeur du champ ordonnee de l’objet point p1 est affectée au champ abscisse de l’objet point courant. Il s’agit bien ici d’une affectation classique puisqu’elle concerne des variables dont les types sont primitifs.. Nous verrons plus tard qu’il est possible de définir des variables de classes pour accueillir des valeurs qui sont identiques pour toutes les instances de la classe.. La déclaration des variables Une règle simple et importante concerne la déclaration des variables, qu’il s’agisse de variables de types primitifs ou de variables objets: elle peut se situer à n’importe quel endroit mais doit toujours précéder l’utilisation de la variable. Cette règle autorise donc des écritures telles Carre monCarre = new Carre(5); double monSalaire, tonSalaire = 4000; monSalaire = tonSalaire/2;. Chapitre 3 Java: notions de base. - 17 -.

(24) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. Une réflexion sur la portée des variables sera nécessaire dans la suite de notre réflexion. Signalons déjà qu’une variable cesse d’exister en dehors du bloc dans lequel elle est définie. Un bloc est délimité par des accolades et peut évidemment contenir d’autres blocs. Ainsi en est-il du bloc de définition d’une classe. La définition d’une méthode ou d’un constructeur est également réalisée dans un bloc. Nous verrons que les blocs apparaissent également au niveau des structures de contrôle des actions mais peuvent aussi être définis n’importe où (pour regrouper plusieurs instructions, par exemple).. La méthode main Si les objets s’envoient les uns les autres des messages de méthodes à exécuter, il faut bien un point de départ. En réalité, une application peut être vue comme une conversation entre objets. L’initiatrice de cette conversation est habituellement une classe qui possède dans sa définition une méthode appelée main. L’application démarre en demandant à la machine Java virtuelle (JVM) d’exécuter la dite classe. La méthode main est alors exécutée. Dans les instructions de celle-ci, on peut trouver des invocations des méthodes des autres objets ou des appels à des constructeurs d’objets d’autres classes. En voici un exemple très court. L’invocation d’objet y est réduite à sa plus simple expression mais ça nous permet de faire quelques commentaires d’ordre syntaxique et de comprendre comment fonctionne une “application”. Un seul objet est invoqué par la méthode main et c’est un objet prédéfini. public class Application1{ public static void main(String args[]){ System.out.println("Bienvenue au cours Java!"); } }. Cet exemple peut paraître bizarre car il ne ressemble guère à ce que nous avons vu jusqu’à présent. La classe ne possède pas de variables d’instance (en fait, elle ne sera jamais instanciée). Son unique méthode est la méthode main. Elle est déclarée static et ses paramètres peuvent sembler curieux. Une méthode est déclarée static lorsqu’il s’agit d’une méthode de classe. Elle ne concerne pas un objet quelconque de la classe, mais la classe elle-même. Nous verrons que lorsqu’une classe possède des variables de classe, elles sont également déclarées static. Le paramètre args[] est en réalité un tableau de chaînes de caractères (String) auquel nous avons donné le nomt args. Ce paramètre désigne un tableau des chaînes de caractères qui peuvent éventuellement suivre la commande d’exécution au niveau du shell de commande. Dans la plupart des exemples que nous utiliserons, ces paramètres seront absents.. Chapitre 3 Java: notions de base. - 18 -.

(25) Programmer avec des objets. Etienne Vandeput ©CeFIS 2002. Vous pourriez également écrire public void main(String[] tableau) ou encore public void main(String table[]). Les syntaxes String[] param et String param[] signifient la même chose à savoir: param est un tableau de String. Notez encore que String est une classe et non un type prédéfini (d’où la majuscule).. Comme toutes les méthodes dynamiques, la méthode println est invoquée sur un objet. Comprendre lequel est un peu plus délicat mais rappelez-vous que nous sommes dans un contexte où tout est objet. out est un champ statique28 (non modifiable) de type PrintStream de la classe non instanciable System. La classe PrintStream est également une classe prédéfinie29. La variable objet out correspond à la sortie standard (souvent l’écran) et prend comme argument une chaîne de caractère. Le travail de cette méthode est d’envoyer la chaîne de caractères vers cette sortie. Ceci nous fait prendre conscience du fait qu’il existe évidemment un nombre considérable de classes prêtes à l’emploi. Sinon, à quoi cela servirait-il de parler de réutilisabilité! Ces classes sont regroupées dans des packages. Une section est également consacrée à leur utilisation. Le package java.lang qui contient la classe System est automatiquement chargé en mémoire à l’exécution d’un programme.. L’exécution du programme Pour pouvoir faire exécuter un programme aussi simple que celui-là, rappelez-vous certaines choses30. Lorsque du code Java est écrit, celui-ci doit être compilé. La compilation produit des octets de code (en anglais, bytecodes), cette espèce de langage universel qui sera interprété au niveau de chaque système par un interpréteur Java qui est propre au système utilisé. La production des octets de codes est réalisée par la commande (le programme) javac. Ce programme est localisé quelque part dans le système de fichiers. Sous Windows, par exemple, il pourrait se trouver dans c:\jdk1.3.1_02\bin. Sous Unix ou Linux, on pourrait le trouver dans /usr/local/bin. La classe qui contient la méthode main doit être enregistrée dans un fichier qui porte le même nom qu’elle et l’extension java. Dans notre exemple, le fichier doit s’appeler Application1.java. Sa compilation javac Application1.java. 28. Les membres de classe peuvent être déclarés statiques. Cela signifie qu’ils ne peuvent plus être modifiés par la suite. Dans ce cas, le mot-clé static est utilisé lors de leur déclaration. Il peut paraître bizarre qu’une méthode (qui est un membre de classe) soit modifiable. Nous verrons que c’est pourtant souvent le cas lorsque nous aurons parlé d’héritage. La méthode main d’une classe application est déclarée static.. 29. Pour une documentation complète des classes prédéfinies et de leurs méthodes, je vous recommande l’adresse suivante http://java.sun.com/j2se/1.4/docs/api/index.html.. 30. Si vous avez sauté la lecture du paragraphe concernant la machine Java virtuelle en fin du chapitre 1, c’est sans doute le moment d’y revenir.. Chapitre 3 Java: notions de base. - 19 -.

Figure

Diagramme de classes

Références

Documents relatifs

a) La qualité de la relation d'attachement joue un rôle modérateur sur l'association entre les pratiques parentales et les troubles du comportement:

Il s’agissait de former rapidement des ouvriers pour les industries d’armement, de faire face à l’explosion du chômage des jeunes et, à partir du régime de Vichy (10 juillet

Résumé Cet article présente un nouveau protocole d’apprentissage de la programmation dans lequel les séquences de travail sont structurées en cycles : d’abord

Dans de nombreux pays, l’universitarisa- tion de la formation des enseignant.e.s a été motivée par le besoin de nourrir ce métier de savoirs issus des sciences de l’éducation,

Un sac circule dans les familles, contenant un album ou un conte bilingue français et langue familiale, une clé USB avec la version numérique du livre (avec capsules sons)

Pour optimiser les conditions favorisant le développement de ces compétences lors des séances de jeux de rôle, les pistes suivantes ont été identifiées à partir d’une

Une réflexion autour d’un travail collectif sur la définition des facettes, des rôles et enjeux du Directeur d’école pourrait permettre de construire une identité partagée

L’archive ouverte pluridisciplinaire HAL, est destinée au dépôt et à la diffusion de documents scientifiques de niveau recherche, publiés ou non, émanant des