Une remarque pertinente ?
Une critique impertinente ?
Un lynchage en règle ?
Une invitation sous les tropiques ?

Ecrivez-moi !
Conçu et enseigné tel qu'en lui même, avec pertes, fracas et humour de qualité supérieure            
 par Christophe Darmangeat dans le M2 PISE du Master MECI (Université Paris 7)            

 
 
 
  

 

 

 

Partie 1

C#, un langage objet


1. C'est quoi, un langage objet ?

Vous le savez sans doute déjà : C# est un langage objet. Ce n'est pas le seul : C++, Java, Visual Basic, pour ne citer que les plus connus, sont eux aussi des langages objets. Ces langages, apparus dans les années 1990, s'oppose à ceux de la génération précédente, qui étaient dits « procéduraux » (comme le Cobol, le Fortran, le Pascal, le C et bien d'autres, on ne va pas tous les citer, on n'a pas que cela à faire non plus).

La première chose à dire des langages objet, c'est qu'ils permettent de faire tout, absolument tout, ce qu'on pouvait faire avec un langage procédural.

Donc, et c'est la bonne nouvelle du jour, rien de ce que vous avez appris n'est perdu ! Les langages objet, comme leurs ancêtres les langages procéduraux, manipulent des variables, des tableaux et des structures, et organisent des instructions d'affectation, d'entrée-sortie, de tests ou de boucles dans des procédures et des fonctions. Donc, à la limite, on peut (presque) programmer en langage objet exactement comme on programmait en langage procédural. Mais évidemment, ce serait bien dommage, car on passerait alors à côté de ces petits riens que les langages objet possèdent en plus, et qui vont nous changer la vie...

  Remarque sournoise :
S'il y a quelque chose que vous ne comprenez pas dans le paragraphe qui précède, c'est vraisemblablement que vous avez doublement brûlé les étapes.
D'une part, en voulant apprendre C# sans avoir appris l'algorithmique.
D'autre part, en n'ayant pas lu assez attentivement les Préambules nécessaires (ce qui n'est pas bien) ou en les ayant lu, et  en choisissant de les ignorer (ce qui est encore pire).
Dans les deux cas, vous n'échapperez pas à un retour par la case départ, et vous ne touchez pas 20 000 F.

Reprenons. Les langages objet, tout en intégrant l'ensemble des capacités des langages procéduraux, possèdent deux aptitudes supplémentaires, aptitudes liées mais distinctes. Ces langages peuvent en effet :

  • gérer, en plus des variables, des tableaux et des structures, des choses appelées objets.
  • exploiter l'interface graphique de Windows.
  Remarque culturelle :
Le nom des langages objets est censé suggérer cette montée en puissance par rapport aux langages traditionnels. C'est ainsi que le plus célèbre des langages procéduraux, le C, a donné naissance à deux principaux avatars objets.
  • le C++, c'est-à-dire le « C augmenté de 1 », puisqu'en C, l'instruction ++ incrémente la variable qui le précède d'une unité.
  • le C#, qui est un clin d'oeil (d'oreille ?) aux musiciens : en anglais, C correspond à notre note Do. Le C#, c'est donc le do dièze, situé juste au-dessus du do.
Et après ça, on dira que les informaticiens ne sont que des geek bouffeurs de pizza et incapables de toute poésie...

Reprenons. On verra plus tard que par contamination, les langages objet ont tendance à tout assimiler à des objets, même des choses qui au départ, n'en étaient pas spécialement, comme les bonnes vieilles variables de notre enfance. Mais n'anticipons pas, et examinons tout d'abord les deux points ci-dessus plus en détail.


1.1 Qu'est-ce qu'un objet ? Parlons comme les gens normaux

Dans la vie de tous les jours, nous sommes entourés d'objets. Certains très simples, comme un peigne, un bouton de culotte ou une matraque de CRS. D'autres très complexes comme une automobile, un ordinateur ou une navette spatiale. Pour faire l'analogie avec les objets des langages objet, mieux vaut penser à un objet un peu compliqué qu'à un objet trop simple. Et pour cette analogie, rien ne nous oblige à penser à un objet inanimé. Des plantes, des animaux ou des êtres humains peuvent tout à fait être assimilés aux objets que manipulent les langages.

Dans les objets, il y a trois sortes de choses qui intéressent les informaticiens.

  • ils possèdent des caractéristiques (une couleur, une taille, un poids, un compte en banque, un nombre de pattes, bref, que sais-je encore). Un objet très simple peut avoir une seule caractéristique (voire aucune, mais là, on peut raisonnablement se demander s'il existe - je laisse cette question aux philosophes désoeuvrés). Un objet complexe peut posséder des centaines, voire des milliers de caractéristiques.
  • ils peuvent accomplir certaines tâches sur demande, ou subir certaines modifications : une automobile peut voir son moteur tourner plus ou moins vite, Un chat peut marcher, courir, miauler, ronronner, etc. Un employé peut travailler, changer de bureau, engueuler son collègue, etc.
  • ils peuvent réagir automatiquement à certains événements : une automobile se met à hurler si on essaye de fracturer la serrure, un chien aussi si le facteur sonne à la porte, le chat court s'il voit une souris, etc.

Tous les objets possédant les mêmes caractéristiques, capables d'accomplir les mêmes tâches sur demande et de réagir automatiquement aux mêmes évènements forment un groupe qu'on appelle en informatique une classe. Par exemple, tous les chiens, et c'est à cela qu'on les reconnaît, ont une couleur de pelage, une taille, un poids, etc. Ils peuvent tous aboyer, courir, sauter, etc. Ils ont donc en commun de posséder certaines caractéristiques et de pouvoir effectuer certaines actions, et font donc partie d'une classe unique que j'appelle « les chiens ». Cela n'empêche nullement chacune de ces aptitudes d'être différente d'un chien à l'autre : le chihuahua de ma cousine est très différent du rottweiler de mon voisin, ma cousine en sait quelque chose lorsqu'elle croise mon voisin. Il n'empêche : tous deux sont des chiens, et pas des porte-manteaux ou des téléviseurs (qui, eux aussi, ont des tailles, des poids et des aptitudes différentes selon les modèles).

En prenant le problème à l'envers : si je définis une classe par l'ensemble de ses caractéristiques et de ses actions, je peux, à partir de cette classe, fabriquer tout plein de toutous différents les uns des autres, mais qui auront en commun d'être tous des chiens (donc, répétons-le lourdement, des êtres qui partageront les mêmes caractéristiques et qui seront capables des mêmes actions).

Eh bien, les langages objet, ce sont des langages qui permettent, en plus des traditionnels variables, tableaux et structures, de gérer et de manipuler des objets (donc des classes). C'est-à-dire que ces langages permettent notamment :

  • de créer des classes, en définissant les caractéristiques et les actions dont seront capables les objets qui en seront issus
  • de fabriquer des objets à partir de ces classes
  • de manipuler les caractéristiques individuelles de chacun de ces objets, et de leur faire accomplir les actions dont ils sont capables.

Tout ce que nous avons vu là peut être traduit dans des termes techniques propres aux informaticiens.


1.2 Qu'est-ce qu'un objet ? Parlons comme les informaticiens

Nous savons que tout programme informatique a pour but de manipuler des informations. Et nous savons que ces informations relèvent toujours, au bout du compte, de l'un des trois grands types simples : numériques, caractères (alphanumériques), ou booléens.

Lorsque nous disons qu'un objet (ou une classe) possède des caractéristiques comme la taille, le poids, la couleur, etc., nous disons en fait qu'un objet (ou une classe) regroupe un certain nombre de variables : une variable numérique pour stocker le poids, une autre variable numérique pour stocker la taille, une variable caractère pour stocker la couleur, etc.

Donc, première chose, un objet regroupe un ensemble de variables qui peuvent être de différents types. Et dans ce cas, on ne parlera pas des « variables » d'un objet, ni des ses « caractéristiques », mais de ses propriétés (ou encore, de ses attributs).

  Définition :
Une propriété d'un objet est une des variables (typée) associées à cet objet.
  Théorème :
Par conséquent, toute instruction légitime avec une variable est légitime avec une propriété d'un objet. Et lycée de Versailles, tout ce qui n'avait pas de sens avec une variable n'a pas non plus de sens avec une propriété d'un objet.

Mais tout cela, allez-vous dire, n'est qu'une manière de faire mousser avec du vocabulaire nouveau une notion bête comme chou et bien connue depuis longtemps. Parce qu'enfin, quoi, un bidule constitué de différentes variables de différents types, on n'a pas attendu les objets pour en avoir. Tous les langages procéduraux connaissent cela, mis à part qu'on ne parle pas de classe mais de structure, qu'on ne parle pas d'objets, mais de variables structurées, et qu'on ne parle pas de propriétés, mais de champs. Mais pour le reste, c'est tutti quanti et du pareil au même.

Les esprits chagrins qui feraient cette remarque auraient parfaitement raison... si les objets n'étaient effectivement qu'un ensemble de caractéristiques (de propriétés). Mais les objets ne sont pas que cela : ils incluent également, comme on l'a vu, des actions possibles. Autrement dit, un objet (une classe) est un assemblage d'informations (les propriétés) mais aussi d'instructions (les actions, que l'on appelle les méthodes) et de réactions automatiques à des évéments. C'est la présence de ces méthodes et de ces événements qui différencie une classe d'une simple structure, et un objet d'une simple variable structurée.

On peut donc dire qu'une classe, c'est une structure plus des méthodes (procédures et fonctions) et des événements.

  Définition :
Une méthode est un ensemble d'instructions associé à un objet (et à sa classe).
Toute méthode est donc une procédure ou une fonction.

Nous mettons donc dès à présent le doigt sur la différence profonde qui existe entre un langage procédural traditionnel et un langage objet : il s'agit de la manière dont sont articulées les informations et les traitements permettant de les modifier.

  • dans un langage procédural, il existe une séparation rigoureuse entre les informations et les traitements. Au cours de l'exécution d'un programme, les informations sont stockées des conteneurs spécifiques (variables, tableaux, structures) et les traitements (instructions) agissent sur ces informations, si j'ose dire, « du dehors ».
  • dans un langage objet, on a regroupé dans une même entité (la classe, donc les objets qui en sont issus) les propriétés et les méthodes, c'est-à-dire les informations et les instructions qui permettent de les manipuler.
 


2. La syntaxe objet

2.1 Généralités

Lorsque nous fabriquions (et nous en fabriquerons encore) une variable, nous utilisions un « moule » à variable, qui s'appelle un type. Pour créer une nouvelle variable, il fallait préciser le type utilisé pour la fabrication de cette variable, par exemple un entier, et lui donner un nom par lequel on la désignerait ensuite tout au long du programme. Dans de nombreux langages– dont le C# – il est même possible de l'affecter directement à la création, par exemple par la valeur 100. D'où la syntaxe :

int toto = 100;

En ce qui concerne les objets, le principe est exactement le même, hormis qu'on ne les fabrique pas d'après un type, mais d'après une classe. Si nous disposons par exemple d'une classe Chien, nous allons pouvoir créer autant de chiens individuels que nous voulons. Voilà par exemple un nouveau compagnon :

Chien Rantanplan = new Chien();

On remarque la présence du mot clé new, propre aux déclarations d'objets, et qui différencie celles-ci des déclarations de variables. On remarque aussi la présence d'une paire de parenthèses après le nom de la classe, ce qui nous évoque irrésistiblement un appel de procédure ou de fonction. Dans le jargon du langage objet, cette instruction new s'appelle un constructeur. Et la réalité est bel est bien conforme aux apparences : en créant un nouvel objet d'après une classe, nous appelons en effet une procédure – plus précisément, une méthode –, le constructeur en question. Dans le cadre de ce cours, nous n'entrerons pas davantage dans ces détails, mais rien ne vous empêche de fouiner le Net pour en apprendre davantage.

  Vocabulaire savant :
Créer un objet d'après une classe s'appelle instancier la classe.
Un objet peut aussi être appelé une instance, ou une occurrence, de la classe.

Notre classe Chien a forcément été créée avec un certain nombre de propriétés et de méthodes. Pour chaque objet instancié selon cette classe, nous pouvons accéder à ces propriétés et à ces méthodes par la syntaxe suivante, universelle :

NomObjet.NomPropriété

Et également :

NomObjet.NomMéthode

  Remarque fondamentale :
Dans un langage objet, on ne peut rencontrer que les deux syntaxes ci-dessus.
Sauf dans des cas exceptionnels, il est impossible de désigner un objet sans le faire suivre d'une propriété ou d'une méthode. C'est une faute de syntaxe.
De même, on ne trouvera jamais une propriété ou une méthode seules, non précédées de l'objet auxquelles elles se réfèrent.
  Remarque fondamentale :
En fait, il y a une troisième circonstance importante dans laquelle on va retrouver une forme « NomObjet.UnTruc ». Mais chaque chose en son temps.


2.2 Propriétés

Admettons pour les besoins de la cause que notre classe Chien possède entre autres propriétés :

  • Taille (float)
  • Poids (integer)
  • Couleur (string)
  • Vacciné (bool)

Alors, je le rappelle, ces propriétés étant en réalité des variables – les champs d'une structure – les règles de leur utilisation sont très exactement les mêmes que celles des variables. Sachant que le signe d'affectation, en C#, est le signe d'égalité, je peux donc écrire :

Rantanplan.Poids = 14;

Et je viens de fixer le poids de mon toutou à 14 kg. Pour le faire grossir de 5 kg, rien de plus simple :

Rantanplan.Poids = Rantanplan.Poids + 5;

...et le tour est joué. Si je veux torturer la pauvre bête, je peux aussi la rendre aussi lourde que haute, en écrivant :

Rantanplan.Poids = Rantanplan.Taille;

L'utilisation de propriétés non numériques ne pose pas davantage de problèmes :

Rantanplan.Couleur = "Beige";

Rantanplan.Vacciné = True;

2.3 Méthodes

Faut-il le répéter, les méthodes sont des fonctions ou des procédures qui ont été définies pour tous les objets d'une classe donnée. Utiliser convenablement une méthode suppose donc de respecter la manière dont la procédure ou la fonction a été écrite. En particulier, comme à chaque fois en pareil cas, il va falloir respecter le nombre et le type des paramètres dont la méthode (la procédure, la fonction) a besoin pour s'exécuter. Ainsi, certaines méthodes peuvent-elles être utilisées sans passer de paramètres. D'autres en exigeront un, d'autres deux, etc.

Lorsque la méthode est un appel de procédure, elle représente en elle-même une instruction à part entière. Lorsqu'elle est un appel de fonction, elle renvoie un résultat. Dans tous les cas, il serait parfaitement absurde d'affecter une méthode comme on affecte une propriété. Les appels aux méthodes pourront donc donner lieu à des lignes du genre :

Rantanplan.Aboyer();

...si la méthode Aboyer s'emploie sans arguments,

Rantanplan.Courir(15);

...si la méthode Courir nécessite un argument numérique, celui fixant la vitesse de course,

Rantanplan.DonnerlaPapatte("gauche");

...si la méthode DonnerlaPapatte réclame un argument de type caractère, etc.

Si vous avez compris cela, vous avez compris 45 % de ce cours. Très exactement, au millipoil près.

     

3. La programmation événementielle

Nous ne sommes pas au bout de nos peines (ni au bout de nos joies). Toute cette histoire d'objets cache une autre plaisanterie, à laquelle j'ai déjà brièvement fait allusion. Celle-ci va radicalement transformer la manière dont les procédures d'un programme vont être exécutées, et du coup, la manière dont les programmeurs vont devoir concevoir leurs applications. Alors, de quoi s'agit-il ?

Rappelons-nous comment notre code était organisé dans un langage procédural traditionnel. Plutôt qu'une immense procédure fait-tout, comportant des redites de code, nos applications, dès lors qu'elles devenaient un peu joufflues, étaient organisées en modules séparés : sous-procédures et fonctions (lesquelles, je le rappelle, ne sont jamais qu'un cas particulier de sous-procédures).

Parmi ces diverses procédures, il s'en trouvait une qui jouait un rôle particulier : la procédure principale (appelée Main dans la plupart des langages). C'est elle qui était exécutée lors du lancement de l'application. Et c'est elle qui tout au long du programme, telle un chef d'orchestre, déclenchait les autres procédures et les autres fonctions.

Le point important dans cette affaire, c'est qu'une fois l'application lancée, une procédure donnée ne pouvait s'exécuter que si une ligne de code, quelque part, en commandait le déclenchement. L'utilisateur n'avait aucune espèce de moyen d'influencer directement l'ordre dans lequel les procédures allaient être exécutées.

Tout ceci est remis en question avec les langages objet. Non qu'on ne puisse plus créer des procédures et des fonctions traditionnelles, et appeler les unes via les autres par des instructions adéquates ; je le rappelle, il n'y a rien qu'on pouvait faire avec un langage procédural qu'on ne puisse faire avec un langage objet. Mais avec un langage objet, on va pouvoir faire certaines choses véritablement inédites. En l'occurrence, la grande nouveauté, c'est qu'on va pouvoir organiser le déclenchement automatique de certaines procédures en réponse à certaines actions de l'utilisateur sur certains objets. Et ces actions, ce sont les fameux événements dont je parlais tout à l'heure.

Pour comprendre cela, le plus simple est de penser à certains objets, qui possèdent un signe particulier : ils se voient à l'écran. Un système d'exploitation tel que Windows est truffé de ce genre d'objets ! Les boutons, les menus, les fenêtres, les cases à cocher, tout cela constitue une armada d'objets visibles, et surtout, capables de réagir aux sollicitations de l'utilisateur via le clavier ou la souris. Les programmeurs qui ont écrit Windows ont donc prévu, et écrit, des myriades de morceaux de code (des procédures) qui se déclenchent à chaque fois que l'utilisateur accomplit telle action sur tel type d'objet, par exemple, le clic sur un bouton, le double-clic sur un raccourci, etc. Donc, concevoir une application événementielle, c'est concevoir des procédures qui se déclencheront automatiquement à chaque fois que l'utilisateur effectuera telle action sur tel objet qu'on aura mis à sa disposition.

  Remarque profonde :
Dans les phrases qui précèdent, les mots « à chaque fois que » sont essentiels. Il faut impérativement les avoir en tête lorsqu'on écrit une application objet.
Faute de quoi on mélange tout, et en particulier, on se met à écrire des boucles là où il n'y a qu'une simple procédure événementielle.
  Définition :
Une action capable de provoquer la réaction d'un objet donné – c'est-à-dire, de déclencher une procédure donnée liée à cet objet – s'appelle un événement.

Voilà pourquoi ce type de programmation porte le nom de programmation événementielle. Par ailleurs, je rappelle que les événements qu'un objet donné est capable de gérer ont été définis dans la classe qui a servi à créer l'objet.

  Remarque importante :
Tous les objets capables de gérer un événement ne sont pas forcément des objets visibles à l'écran. Dans le même ordre d'idées, tous les événements ne correspondent pas forcément à des actions de l'utilisateur via le clavier ou la souris. Mais pour commencer, on peut très bien s'accommoder de ces approximations.


3.1 Le diagramme T.O.E.

Lors de la conception d'un programme objet, une des premières tâches du développeur va donc être de concevoir l'interface utilisateur. C'est-à-dire de prévoir quels objets vont être mis à sa disposition à l'écran, quelles seront les actions qu'il pourra effectuer sur ces objets (c'est-à-dire les événements qu'il pourra déclencher) et de prévoir les tâches que le programme devra accomplir lors de ces événements.

Pour le moment, nous nous contenterons de considérer que nos applications emploient uniquement l'arsenal des objets utilisés par Windows. Ces objets (plus exactement, ces classes) seront donc tout prêts à l'emploi. Leurs propriétés, leurs méthodes et les événements qu'ils sont capables de gérer ont été définis par Windows, plus exactement par le Framework .NET (une couche logicielle qui sert d'intermédiaire entre C# et Windows, qui parle un langage trop abscons pour nous).

En réalité, dans un programme C#, on peut utiliser des tas d'autres objets (classes) et on peut même en fabriquer soi-même. Nous verrons cela... un peu, et plus tard. Pour le moment, on se contentera de la trousse à outils que le Framework .NET met à notre disposition, ce qui suffira déjà à nous procurer de longues heures de bonheur.

Ainsi, nous pouvons prévoir qu'il faudra que la fenêtre de notre application se présente comme ceci ou comme cela, qu'il devra y avoir ici un bouton, là des boutons radios, ici une zone de liste, etc. Et il faut également prévoir qu'un clic sur tel bouton déclenchera tel ou tel calcul, qu'un choix dans telle liste devra mettre à jour telle ou telle zone, etc.

Le document synthétique, sous forme de tableau, qui reprend toutes ces informations, s'appelle un diagramme T.O.E., pour Tâche, Objet, Événement. C'est un document préalable indispensable à la programmation d'une application événementielle. Il comporte trois colonnes. Dans la première, on dresse la liste exhaustive des tâches que doit accomplir l'application. Dans la seconde, en regard de chaque tâche à accomplir, on porte, le cas échéant, le nom de l'objet qui en sera chargé. Et dans la troisième, en regard de chaque objet, on écrit le cas échéant, mais oui, l'événement correspondant. Vous l'aviez deviné ? Décidément vous êtes trop forts.

  Remarque importante :
Rien n'impose qu'un objet soit associé à un événement et à un seul. Certains objets peuvent fort bien n'être associés à aucun événement. De même, d'autres objets peuvent très bien gérer plusieurs événements différents, qui correspondront donc à autant de procédures différentes.

Nous verrons très bientôt comment crééer une procédure événementielle en C#. En attendant, si vous avez compris le mécanisme des procédures événementielles, alors vous avez alors pigé 45 % supplémentaires du cours. Donc, avec les 45 % précédents (ceux des classes, des objets, des propriétés et des méthodes), on en est à 90 %. Tout le reste, c'est de la petite bière. Puisque je vous le dis.