Attention, ce cours est un cours «dépannage», il a été construit afin de pallier à l’absence soudaine et longue d’un collègue. Il est l’œuvre conjointe de Olivier Carton, Yann Régis-Gianas et moi-même.
Pré-requis
Ce cours peut-être suivi par tout étudiant ayant des connaissances minimales en programmation.
Contenu
Le cours contient essentiellement deux éléments :
- l’étude du langage Java et de la programmation objet
- son application à la programmation d’interfaces graphiques
Cours
Premier cours
Un peu de modélisation, de réalisation et de principe d’encapsulation…
L’écriture UML de la spécification abstraite :
L’écriture UML de la spécification concrète :
Les codes correspondants : Le programme principal et le dé
Second cours
Encore un peu de modélisation, de réalisation et de relations (simple association et composition)
L’écriture UML exposée :
Les codes correspondants : Le programme principal, le dé, le joueur, le plateau et la case
Troisième cours
L’écriture UML des abstractions et implémentations des différents dés :
Le code complet et fonctionnel (pas le meilleur des codes, mais il possède déjà quelques avantages) sous forme d’une archive, l’interface De, le dé à 6 faces, le dé pipé, le dé à 6 faces qui comptabilise les tirages, le dé à 6 faces qui trace à l’écran son usage, le joueur, la liste des joueurs, le pion, les mouvements des pions, le plateau et les cases, le jeu et le programme principal.
Quatrième cours
Retour sur les diagrammes etl la programmation objet. Les classes abstraites. Sous-typage structurel vs sémantique. Factorisation de code. Confiance dans le sous-typage. Factory. Packaging. Contrat d’utilisation. Contrat de construction.
Le code packagé et sensiblement amélioré du jeu de l’oie
Cinquième cours
Retour sur le code de la semaine précédente. Liaison dynamique et résolution des appels. Généralisation de la notion de plateau et pion. La classe racine Object. Downcast et ses problèmes. Les wrappers des types de base.
Le code packagé et nettement amélioré du jeu de l’oie
Sixième cours
Retour sur ce qui a été fait la dernière fois. Retour sur les constructeurs. Retour rapide sur la syntaxe des constructeurs. Est-ce que le constructeur de la classe mère est appelé ? À quoi ça peut servir de n’avoir que des constructeurs privés dans une classe ? .clone() deep or shallow copy ? L’interface cloneable. Retour sur le jeu de l’oie : introductions des sorts! Conception/Implémentation. On utilise Object pour représenter le contenu des cases. Les cases contiennent maintenant des pions et des sorts. Quand un pion arrive le premier sur un sort, le sort est appliqué sur le plateau et les joueurs. Comment notifier un sort qu’un pion arrive sur une case? Comment autoriser les sorts à être placés dynamiquement sur les cases? Le “fork” le joueur est cloné, il devra maintenant jouer le double de tour (Prétexte pour un retour sur .clone()). Le “bazar” les joueurs échangent leurs pions suivant une permutation aléatoire (Prétexte pour chercher une fonctionnalité dans la bibliothèque.) L’«effroyable hésitation» le pion du joueur est transformé en pion hésitant qui tire à pile ou face avant de se déposer sur une case et si il tombe sur face, décide de rester où il est. Heureusement, cette fonctionnalité ne dure que 2 tours (Prétexte pour parler de décorateur.)
Le code packagé du jeu de l’oie
Septième cours
- Surcharge
- définition : utiliser un même nom pour deux méthodes différentes.
- méthode de résolution
- interaction entre redéfinition et surcharge
- application : définir une égalité binaire
- Des objets curieux
- Patron de conception “Sujet-Observateurs” Le moteur du jeu de l’oie fait explicitement l’affichage de l’état du jeu et de ses événements. Comment séparer cet aspect “affichage” du moteur (qui devrait seulement être responsable de la logique du jeu)?
- Première tentative : on créé un objet “Afficheur” et le moteur l´appelle. C’est mieux mais toujours insatisfaisant : si on veut faire un objet qui enregistre dans un fichier chaque événement de jeu alors il faut aussi que le moteur l’appelle aussi explicitement…
- Seconde solution : introduire le concept d’observateur du jeu qui s’inscrit auprès du moteur pour être averti des différents événements. (Encore un prétexte pour introduire des classes abstraites et un protocole entre objets.)
- Patron de conception “Sujet-Observateurs” Le moteur du jeu de l’oie fait explicitement l’affichage de l’état du jeu et de ses événements. Comment séparer cet aspect “affichage” du moteur (qui devrait seulement être responsable de la logique du jeu)?
- Exceptions
- exemples: division par zéro, allocation de 32Go de RAM, fin d’un fichier.
- call stack et “try catch finally” sur les exemples précédents
- “Catch or Specify”
- Classification des exceptions: checked exception, error, runtime exception:
- Les ‘checked exceptions’ doivent suivre le Catch or Specify.
- Les erreurs sont “unchecked” et on n’est pas supposé y survivre (erreur dans une couche basse, OS ou JVM)
- Les “runtime exceptions” sont “unchecked” et on peut éventuellement y survivre (erreur dans une couche logique, mais ce n’est pas forcément une bonne idée de l’ignorer car il s’agit d’un bug)
- Observation de RuntimeException and Error: pourquoi Error n’est-elle pas une sous-classe de Exception? Pourquoi les RuntimeExceptions ne sont pas checked?
- throw
- https://docs.oracle.com/javase/tutorial/essential/exceptions/advantages.html
- pas vu le try-with-ressource et le try-finally (sans catch)
- Generics
- Motivations: supprimer les casts.
- Syntaxe pour la définition de classes et méthodes paramétrés et leurs usages.
- Dans le jeu de l’oie le plateau est paramétré par le type des pions
- Bounded parameters
- Raw type, type erasure, unchecked conversion
Le code packagé du jeu de l’oie
Huitième cours
Collections
Les API de Java fournissent une grande variété de structures de données, déjà codées avec leurs fonctionnalités, permettant de stocker et de manipuler des éléments. Ces structures de données sont appelées de façon générique des collections et sont représentées par l’interface Collection
du package java.util
En réalité, certaines structures de données appelées table
et représentées par l’interface Map
ne sont pas considérées comme des collections: la hierarchie des principales classes concernées est donnée par le schéma à la fin de cette page.
En fait, cette interface est la plus générale de toutes les collections et possède différents sous-types (sous-interfaces et/ou classes abstraites) qui conduisent à quelques classes concrètes implantant des fonctionnalités de types de collection particuliers. Le dessin ci-dessous représente schématiquement leur organisation.
La hiérarchie des collections
Les deux grandes catégories de collections sont :
- les ensembles, correspondant à l’interface
Set
, qui représentent les collections qui ne dupliquent pas leurs éléments (ajouter un élément à un ensemble qui le contient déjà est sans effet). La sous-interfaceSortedSet
correspond à une vue ordonnée (par ordre croissant) des éléments d’un tel ensemble. Cela implique soit que ces éléments sont comparables (ils implantent l’interfacejava.lang.Comparable
), soit que l’on en fournisse un comparateur (java.util.Comparator
). - les listes ou séquences, correspondant à l’interface
List
, qui représentent les suites d’éléments avec potentiellement plusieurs occurrences d’un même élément. L’accès aux éléments de ces collections se fait via un index dans la liste.
Schémas d’itération
Un itérateur (interface Iterator
) est un objet qui permet de parcourir les éléments d’une collection. Un itérateur possède deux méthodes essentielles de noms hasNext()
et next
. La première méthode permet de savoir s’il reste des éléments à parcourir alors que la seconde retourne l’élément courant et fait avancer l’itérateur qui passe à l’élément suivant. Il faut toujours vérifier avec hasNext
qu’il reste encore des éléments avant d’appeler next()
. Chacune des collections possède une méthode iterator()
qui retourne un itérateur permettant de parcourir ses éléments. Une boucle typique pour parcourir les éléments d’une collection c
a la forme.
for (Iterator it = c.iterator(); it.hasNext(); ) {
Object o = it.next());
...
}
Cette boucle typique peut aussi être écrite de la façon suivante:
for (Object o : c) {
...
}
Associations
La hiérarchie des maps
Neuvième cours: interactions
Premières fenêtres :
- Un programme minimal qui se contente d’ouvrir une fenêtre.
- Un programme qui ouvre une simple fenêtre sans rien afficher dedans.
- Un programme qui dessine une ligne en diagonal.
Interactions : menus et boutons
- Une application avec trois boutons pour changer la couleur du fond (version avec une classe externe).
- Une application avec trois boutons pour changer la couleur du fond (version avec une classe interne nommée).
- Une application avec trois boutons pour changer la couleur du fond (version avec une classe interne anonyme).
- Une application avec un menu dans la barre de menu pour changer la couleur du fond.
Dixième cours: disposition et architecture
Gestionnaires de disposition
- Une application pour jouer avec les gestionnaires de disposition.
- Programmes Demo1, Demo2, Demo3 et Demo4 de démonstration du gestionnaire
GridBaglayout
.
Architecture Modèle/Vue/Contrôleur
- Exemple d’utilisation de l’architecture modèle/vue/contrôleur.