Introduction sur les Objets
La genèse de la révolution informatique fut dans l’invention d’une machine. La genèse de nos langage de programmation tend donc à ressembler à cette machine. Mais les ordinateurs ne sont pas tant des machines que des outils d’amplification de l’esprit(« des vélos pour le cerveau », comme aime à le répéter Steve Jobs) et un nouveau moyen d’expression. Ainsi, ces outils commencent à ressembler moins à des machines et plus à des parties de notre cerveau ou d’autres moyens d’expressions telles que l’écriture, la peinture, la sculpture ou la réalisation de films. La Programmation Orientée Objet fait partie de cette tendance de l’utilisation de l’ordinateur en tant que moyen d’expression. Ce chapitre présente les concepts de base de la programmation orientée objet (POO), ainsi qu’un survol des méthodes de développement de la POO. Ce chapitre et ce livre présupposent que vous avez déjà expérimenté un langage de programmation procédural, qui ne soit pas forcément le C. Si vous pensez que vous avez besoin de plus de pratique dans la programmation et/ou la syntaxe du C avant de commencer ce livre, vous devriez explorer le CD ROM fourni avec le livre, Thinking in C: Foundations for C++ and Java, également disponible sur www.BruceEckel.com.Ce chapitre tient plus de la culture générale. Beaucoup de personnes ne veulent pas se lancer dans la programmation orientée objet sans en comprendre d’abord les tenants et les aboutissants. C’est pourquoi beaucoup de concepts seront introduits ici afin de vous donner un solide aperçu de la POO. Au contraire, certaines personnes ne saisissent les concepts généraux qu’après en avoir compris une partie des mécanismes; ces gens-là se sentent embourbés et perdus s’ils n’ont pas un bout de code à se mettre sous la dent. Si vous faites partie de cette catégorie de personnes et êtes impatients d’attaquer les spécificités du langage, vous pouvez sauter ce chapitre – cela ne vous gênera pas pour l’écriture de programmes ou l’apprentissage du langage. Mais vous voudrez peut-être y revenir plus tard pour approfondir vos connaissances sur les objets, les comprendre et assimiler la conception objet.
Les bienfaits de l’abstraction
Tous les langages de programmation fournissent des abstractions. On peut dire que la complexité des problèmes que vous êtes capable de résoudre est directement proportionnelle au type et à la qualité d’abstraction. Par « type », il faut comprendre « Que tentez-vous d’abstraire ? ». Le langage assembleur est une petite abstraction de la machine sous-jacente. Beaucoup de langages « impératifs » (tels que Fortran, BASIC, et C) sont des abstractions du langage assembleur. Ces langages sont de nettes améliorations par rapport à l’assembleur, mais leur abstraction première requiert que vous réfléchissiez en termes de structure de l’ordinateur plutôt qu’à la structure du problème que vous essayez de résoudre. Le programmeur doit établir l’association entre le modèle de la machine (dans « l’espace solution », qui est le lieu où vous modélisez le problème, tel que l’ordinateur) et le modèle du problème à résoudre (dans « l’espace problème », qui est l’endroit où se trouve le problème). Les efforts requis pour réaliser cette association, et le fait qu’elle est étrangère au langage de programmation, produit des programmes difficiles à écrire et à entretenir, ce qui a mené à la création de l’industrie du « Génie Logiciel». L’alternative à la modélisation de la machine est de modéliser le problème que vous tentez de résoudre. Les premiers langages tels que LISP ou APL choisirent une vue particulière du monde (« Tous les problèmes se ramènent à des listes » ou « Tous les problèmes sont algorithmiques »). PROLOG convertit tous les problèmes en chaînes de décision. Des langages ont été créés pour la programmation par contrainte, ou pour la programmation ne manipulant que des symboles graphiques (ces derniers se sont révélés être trop restrictifs). Chacune de ces approches est une bonne solution pour la classe particulière de problèmes qu’ils ont a résoudre, mais devient plus délicate dès lors que vous les sortez de leur domaine. L’approche orientée objet va un pas plus loin en fournissant des outils au programmeur pour représenter des éléments dans l’espace problème. Cette représentation est assez générale pour que le programmeur ne soit restreint à aucun type particulier de problème. Nous nous référons aux éléments dans l’espace problème et leur représentation dans l’espace solution en tant qu’« objets ». (Bien sûr, vous aurez aussi besoin d’autres objets qui n’ont pas leur analogue dans l’espace problème). L’idée est qu’on permet au programme de s’adapter au fond du problème en ajoutant de nouveaux types d’objets , de façon à ce que, quand vous lisez le code décrivant la solution, vous lisez aussi quelque chose qui décrit le problème. C’est un langage d’abstraction plus flexible et puissant que tout ce que nous avons eu jusqu’à présent. Ainsi, la POO vous permet de décrire le problème selon les termes du problème plutôt que selon les termes de la machine sur laquelle la solution sera exécutée. Cependant, il y a toujours une connexion à l’ordinateur. Chaque objet ressemble à un mini-ordinateur ; il a un état, et il a des opérations que vous pouvez lui demander d’exécuter. Cependant, cela ne semble pas être une si mauvaise analogie avec les objets du monde réel – ils ont tous des caractéristiques et des comportements.
Des concepteurs de langage ont décrété que la programmation orientée objet en elle-même n’était pas adéquate pour résoudre facilement tous les problèmes de programmation, et recommandent la combinaison d’approches variées dans des langages de programmation multiparadigmes.
Alan Kay a résumé les cinq caractéristiques de base de Smalltalk, le premier véritable langage de programmation orienté objet et l’un des langages sur lequel est basé C++. Ces caractéristiques représentent une approche pure de la programmation orientée objet :
1 Toute chose est un objet. Pensez à un objet comme à une variable améliorée : il stocke des données, mais vous pouvez « effectuer des requêtes » sur cet objet, lui demander de faire des opérations sur lui-même. En théorie, vous pouvez prendre n’importe quel composant conceptuel du problème que vous essayez de résoudre (un chien, un immeuble, un service administratif, etc…) et le représenter en tant qu’objet dans le programme. 2 Un programme est un groupe d’objets s’indiquant quoi faire en envoyant des messages. Pour qu’un objet effectue une requête, vous « envoyez un message » à cet objet. Plus concrètement, vous pouvez penser à un message comme à un appel de fonction appartenant à un objet particulier. 3 Chaque objet a sa propre mémoire composée d’autres objets. Autrement dit, vous créez un nouveau type d’objet en créant un paquetage contenant des objets déjà existants. Ainsi, vous pouvez créer un programme dont la complexité est cachée derrière la simplicité des objets. 4 Chaque objet a un type. Dans le jargon, chaque objet est une instance d’une classe, où « classe » est synonyme de « type ». La caractéristique distinctive la plus importante d’une classe est : « Quels messages pouvez-vous lui envoyer ? ». 5 Tous les objets d’un type particulier peuvent recevoir les mêmes messages. C’est une caractéristique lourde de signification, comme vous le verrez plus tard. Parce qu’un objet de type « cercle » est également un objet de type « forme », un cercle garanti d’accepter les messages de forme. Cela signifie que vous pouvez écrire du code qui parle aux formes et qui sera automatiquement accepté par tout ce qui correspond à la description d’une forme. Cette substituabilité est l’un des concepts les plus puissants de la POO.
Un objet dispose d’une interface
Aristote fut probablement le premier à commencer une étude approfondie du concept de type; il parle de « la classe des poissons et la classe des oiseaux ». L’idée que tous les objets, tout en étant uniques, appartiennent à une classe d’objets qui ont des caractéristiques et des comportements en commun fut utilisée directement dans le premier langage orienté objet, Simula-67, avec son mot clef fondamental class qui introduit un nouveau type dans un programme.
Simula, comme son nom l’indique, a été conçu pour développer des simulations telles que « le problème du guichet de banque » Vous trouverez une implémentation intéressante de ce problème dans le Volume 2 de ce livre, disponible sur www.BruceEckel.com.Dans celle-ci, vous avez un ensemble de guichetiers, de clients, de comptes, de transactions et de devises – un tas « d’objets ». Des objets semblables, leur état durant l’exécution du programme mis à part, sont groupés ensemble en tant que « classes d’objets » et c’est de là que vient le mot clef class. Créer des types de données abstraits (des classes) est un concept fondamental dans la programmation
orientée objet. On utilise les types de données abstraits de manière quasi identique aux types de données prédéfinis. On peut créer des variables d’un type particulier (appelés objets ou instances dans le jargon orienté objet) et manipuler ces variables (ce qu’on appelle envoyer des messages ou des requêtes; on envoie un message et l’objet se débrouille pour le traiter). Les membres (éléments) d’une même classe partagent des caractéristiques communes : chaque compte dispose d’un solde, chaque guichetier peut accepter un dépôt, etc. Cependant, chaque élément a son propre état, chaque compte a un solde différent, chaque guichetier a un nom. Ainsi, les guichetiers, clients, comptes, transactions, etc. peuvent tous être représentés par une unique entité au sein du programme. Cette entité est l’objet, et chaque objet appartient à une classe particulière qui définit ses caractéristiques et ses comportements.
Donc, comme la programmation orientée objet consiste en la création de nouveaux types de données, quasiment tous les langages orientés objet utilisent le mot clef « class ». Quand vous voyez le mot « type » pensez « classe » et inversement Certains font une distinction, au motif que le type détermine l’interface tandis que la classe est une implémentation particulière de cette interface.
Comme une classe décrit un ensemble d’objets partageant des caractéristiques (données) et des comportements (fonctionnalités) communs, une classe est réellement un type de données. En effet, un nombre en virgule flottante par exemple, dispose d’un ensemble de caractéristiques et de comportements. La différence est qu’un programmeur définit une classe pour représenter un problème au lieu d’être forcé d’utiliser un type de données conçu pour représenter une unité de stockage de l’ordinateur. Le langage de programmation est étendu en ajoutant de nouveaux types de données spécifiques à nos besoins. Le système de programmation accepte la nouvelle classe et lui donne toute l’attention et le contrôle de type qu’il fournit aux types prédéfinis.
L’approche orientée objet n’est pas limitée aux simulations. Que vous pensiez ou non que tout programme n’est qu’une simulation du système qu’on représente, l’utilisation des techniques de la POO peut facilement réduire un ensemble de problèmes à une solution simple.
Une fois qu’une classe est créée, on peut créer autant d’objets de cette classe qu’on veut et les manipuler comme s’ils étaient les éléments du problème qu’on tente de résoudre. En fait, l’une des difficultés de la programmation orientée objet est de créer une bijection entre les éléments de l’espace problème et les éléments de l’espace solution.