IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Penser en Java 2nde édition - Sommaire |  Préface |  Avant-propos | Chapitre : 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15 |  Annexe : A B C D  | Tables des matières - Thinking in Java

  Chapitre 8 - Interfaces et classes internes

pages : 1 2 3 4 5 6 

La plupart des classes Event sont similaires, mais Bell et Restart sont spéciales. Bell sonne, et si elle n'a pas sonné un nombre suffisant de fois, elle ajoute un nouvel objet Bell à la liste des événements afin de sonner à nouveau plus tard. Notez comme les classes internes semblent bénéficier de l'héritage multiple : Bell possède toutes les méthodes d'Event mais elle semble disposer également de toutes les méthodes de la classe externe GreenhouseControls.

Restart est responsable de l'initialisation du système, il ajoute donc tous les événements appropriés. Bien sûr, une manière plus flexible de réaliser ceci serait d'éviter le codage en dur des événements et de les extraire d'un fichier à la place (c'est précisément ce qu'un exercice du Chapitre 11 demande de faire). Puisque Restart() n'est qu'un objet Event comme un autre, on peut aussi ajouter un objet Restart depuis Restart.action() afin que le système se relance de lui-même régulièrement. Et tout ce qu'on a besoin de faire dans main() est de créer un objet GreenhouseControls et ajouter un objet Restart pour lancer le processus.

Cet exemple devrait vous avoir convaincu de l'intérêt des classes internes, spécialement dans le cas des structures de contrôle. Si ce n'est pas le cas, dans le Chapitre 13, vous verrez comment les classes internes sont utilisées pour décrire élégamment les actions d'une interface graphique utilisateur. A la fin de ce chapitre vous devriez être complètement convaincu.

Résumé

Les interfaces et les classes internes sont des concepts plus sophistiqués que ce que vous pourrez trouver dans beaucoup de langages de programmation orientés objets. Par exemple, rien de comparable n'existe en C++. Ensemble, elles résolvent le même problème que celui que le C++ tente de résoudre avec les fonctionnalités de l'héritage multiple. Cependant, l'héritage multiple en C++ se révèle relativement ardu à mettre en oeuvre, tandis que les interfaces et les classes internes en Java sont, en comparaison, d'un abord nettement plus facile.

Bien que les fonctionnalités en elles-mêmes soient relativement simples, leur utilisation relève de la conception, de même que le polymorphisme. Avec le temps, vous reconnaîtrez plus facilement les situations dans lesquelles utiliser une interface, ou une classe interne, ou les deux. Mais à ce point du livre vous devriez à tout le moins vous sentir à l'aise avec leur syntaxe et leur sémantique. Vous intègrerez ces techniques au fur et à mesure que vous les verrez utilisées.

Exercices

Les solutions d'exercices sélectionnés peuvent être trouvées dans le document électronique The Thinking in Java Annotated Solution Guide, disponible pour un faible coût sur www.BruceEckel.com.

  1. Prouvez que les champs d'une interface sont implicitement static et final.
  2. Créez une interface contenant trois méthodes, dans son propre package. Implémentez cette interface dans un package différent.
  3. Prouvez que toutes les méthodes d'une interface sont automatiquement public.
  4. Dans c07:Sandwich.java, créez une interface appelée FastFood (avec les méthodes appropriées) et changez Sandwich afin qu'il implémente FastFood.
  5. Créez trois interfaces, chacune avec deux méthodes. Créez une nouvelle interface héritant des trois, en ajoutant une nouvelle méthode. Créez une classe implémentant la nouvelle interface et héritant déjà d'une classe concrète. Ecrivez maintenant quatre méthodes, chacune d'entre elles prenant l'une des quatre interfaces en argument. Dans main(), créez un objet de votre classe et passez-le à chacune des méthodes.
  6. Modifiez l'exercice 5 en créant une classe abstract et en la dérivant dans la dernière classe.
  7. Modifiez Music5.java en ajoutant une interfacePlayable. Enlevez la déclaration de play() d'Instrument. Ajoutez Playable aux classes dérivées en l'incluant dans la liste implements. Changez tune() afin qu'il accepte un Playable au lieu d'un Instrument.
  8. Changez l'exercice 6 du Chapitre 7 afin que Rodent soit une interface.
  9. Dans Adventure.java, ajoutez une interface appelée CanClimb respectant la forme des autres interfaces.
  10. Ecrivez un programme qui importe et utilise Month2.java.
  11. En suivant l'exemple donné dans Month2.java, créez une énumération des jours de la semaine.
  12. Créez une interface dans son propre package contenant au moins une méthode. Créez une classe dans un package séparé. Ajoutez une classe interne protected qui implémente l'interface. Dans un troisième package, dérivez votre classe, et dans une méthode renvoyez un objet de la classe interne protected, en le transtypant en interface durant le retour.
  13. Créez une interface contenant au moins une méthode, et implémentez cette interface en définissant une classe interne à l'intérieur d'une méthode, qui renvoie une référence sur votre interface.
  14. Répétez l'exercice 13 mais définissez la classe interne à l'intérieur d'une portée à l'intérieur de la méthode.
  15. Répétez l'exercice 13 en utilisant une classe interne anonyme.
  16. Créez une classe interne private qui implémente une interface public. Ecrivez une méthode qui renvoie une référence sur une instance de la classe interne private, transtypée en interface. Montrez que la classe interne est complètement cachée en essayant de la transtyper à nouveau.
  17. Créez une classe avec un constructeur autre que celui par défaut et sans constructeur par défaut. Créez une seconde classe disposant d'une méthode qui renvoie une référence à la première classe. Créez un objet à renvoyer en créant une classe interne anonyme dérivée de la première classe.
  18. Créez une classe avec un champ private et une méthode private. Créez une classe interne avec une méthode qui modifie le champ de la classe externe et appelle la méthode de la classe externe. Dans une seconde méthode de la classe externe, créez un objet de la classe interne et appelez sa méthode ; montrez alors l'effet sur l'objet de la classe externe.
  19. Répétez l'exercice 18 en utilisant une classe interne anonyme.
  20. Créez une classe contenant une classe interne static. Dans main(), créez une instance de la classe interne.
  21. Créez une interface contenant une classe interne static. Implémentez cette interface et créez une instance de la classe interne.
  22. Créez une classe contenant une classe interne contenant elle-même une classe interne. Répétez ce schéma en utilisant des classes internes static. Notez les noms des fichiers .class produits par le compilateur.
  23. Créez une classe avec une classe interne. Dans une classe séparée, créez une instance de la classe interne.
  24. Créez une classe avec une classe interne disposant d'un constructeur autre que celui par défaut. Créez une seconde classe avec une classe interne héritant de la première classe interne.
  25. Corrigez le problème dans WindError.java.
  26. Modifiez Sequence.java en ajoutant une méthode getRSelector() qui produise une implémentation différente de l'interface Selector afin de parcourir la séquence en ordre inverse, de la fin vers le début.
  27. Créez une interface U contenant trois méthodes. Créez une classe A avec une méthode qui produise une référence sur un U en construisant une classe interne anonyme. Créez une seconde classe B qui contienne un tableau de U. B doit avoir une méthode qui accepte et stocke une référence sur un U dans le tableau, une deuxième méthode qui positionne une référence (spécifiée par un argument de la méthode) dans le tableau à null, et une troisième méthode qui se déplace dans le tableau et appelle les méthodes de l'objet U. Dans main(), créez un groupe d'objets A et un objet B. Remplissez l'objet B avec les références U produites par les objets A. Utilisez B pour revenir dans les objets A. Enlevez certaines des références U de B.
  28. Dans GreenhouseControls.java, ajoutez des classes internes Event qui contrôlent des ventilateurs.
  29. Montrez qu'une classe interne peut accéder aux éléments private de sa classe externe. Déterminez si l'inverse est vrai.

[38]Cette approche m'a été inspirée par un e-mail de Rich Hoffarth.

[39]Merci à Martin Danner pour avoir posé cette question lors d'un séminaire.

[40]Ceci est très différent du concept des classes imbriquées en C++, qui est simplement un mécanisme de camouflage de noms. Il n'y a aucun lien avec l'objet externe et aucune permission implicite en C++.

[41]Merci encore à Martin Danner.

[42]Attention cependant, '$' est un méta-caractère pour les shells unix et vous pourrez parfois rencontrer des difficultés en listant les fichiers .class. Ceci peut paraître bizarre de la part de Sun, une entreprise résolument tournée vers unix. Je pense qu'ils n'ont pas pris en compte ce problème car ils pensaient que l'attention se porterait surtout sur les fichiers sources.

[43]Pour je ne sais quelle raison, ce problème m'a toujours semblé plaisant ; il vient de mon livre précédent C++ Inside & Out, mais Java offre une solution bien plus élégante.

Ce livre a été écrit par Bruce Eckel ( télécharger la version anglaise : Thinking in java )
Ce chapitre a été traduit par Jérome Quelin ( groupe de traduction )
télécharger la version francaise (PDF) | Commandez le livre en version anglaise (amazon) | télécharger la version anglaise
pages : 1 2 3 4 5 6 
Penser en Java 2nde édition - Sommaire |  Préface |  Avant-propos | Chapitre : 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15 |  Annexe : A B C D  | Tables des matières - Thinking in Java