• 12 heures
  • {0} Facile|{1} Moyenne|{2} Difficile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 30/04/2014

La POO dans tous ses états

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Nous allons maintenant attaquer la deuxième partie du cours, traitant d'une notion très importante en Actionscript 3 : la Programmation Orientée Objet (ou POO).
Appréhender cette notion sera peut-être difficile au début, mais vous finirez par tomber sous le charme de cette façon de programmer, je vous le promets !

Cette partie sera également l'occasion de faire (enfin !) un peu de pratique à l'occasion de quelques exercices que nous réaliserons ensemble.

Attachez vos ceintures, c'est parti ! La POO n'aura bientôt plus aucun secret pour vous ! :zorro:

Les notions-clés

Il était une fois... un objet

Vous avez sûrement une idée de ce qu'est un objet : dans la vie de tous les jours, nous en voyons, nous en touchons des centaines. Ils ont chacun une forme et remplissent une ou plusieurs tâches. On distingue rapidement plusieurs catégories d'objets qui se ressemblent : quand vous mettez la table, vous manipulez des objets (fourchettes, couteaux, cuillères, ...) appartenant à la catégorie « couvert ». Bien sûr, vous pouvez avoir plusieurs objets de cette catégorie, voire plusieurs fourchettes identiques. Les objets de la catégorie « fourchette » font également partie de la catégorie « couvert » car les fourchettes ne sont en fait que des couverts particuliers.

La programmation orientée objet part de ces différentes observations pour introduire de nouveaux concepts en programmation afin de rendre le développement de logiciels plus efficace et intuitif.

L'Objet

Prenons une de vos fourchettes.

Une fourchette (image de ArnoldReinhold, tirée du site Wikimedia Commons)
Une fourchette (image de ArnoldReinhold, tirée du site Wikimedia Commons)

Il s'agit d'un objet ayant une forme particulière et une certaine utilité, caractéristiques que l'on peut retrouver dans les autres fourchettes. Un objet en programmation est également une entité possédant des propriétés que l'on peut retrouver sur d'autres objets de la même catégorie. Il ne s'agit ni d'une variable, ni d'une fonction, mais d'un mélange des deux : c'est un nouveau concept à part entière.
Un objet peut donc contenir plusieurs variables (appelées attributs) et plusieurs fonctions (appelées méthodes). Ces variables et fonctions (appelées propriétés) sont profondément liées à l'objet qui les contient : les attributs stockent des informations sur cet objet. Par exemple, si mon objet « fourchette » possède un attribut « poids », cet attribut représente la masse de cette fourchette et non la masse d'une autre fourchette posée à côté.

La Classe

Seulement, vous avez sur votre table non pas une mais dix fourchettes, quoique pas exactement identiques. En effet, cette fourchette ci et plus légère que cette fourchette là, donc son attribut « poids » est plus faible. Mais ces deux objets restent des fourchettes, malgré leur différence de poids. Fourchette est donc la catégorie de ces objets, appelée classe.

Une classe décrit la nature de ses objets : c'est un schéma permettant de fabriquer et de manipuler plusieurs objets possédant les mêmes attributs et méthodes. Par exemple, la classe Fourchette pourrait décrire les attributs « poids », « taille », « nombre de dents », etc.

La classe Fourchette et quelques instances
La classe Fourchette et quelques instances

Nous pourrions aussi créer une classe Couteau pour les couteaux, et une classe Cuillère pour les cuillères.

Un autre exemple

Une fois la table mise, vous tournez la tête et admirez à travers la fenêtre votre magnifique voiture toute neuve : ne serait-ce pas un objet de la classe Voiture ? Avec un objet aussi complexe, cette classe contient certainement plus d'attributs et de méthodes que la classe Fourchette...

Votre magnifique voiture
Votre magnifique voiture

Voici quelques exemples d'attributs : « taille » (un grand classique), « marque », « couleur », « nombre de pneus », « nombre de sièges » ; et quelques exemples de méthodes : « verrouiller les portières », « démarrer le moteur », « accélérer », « freiner », « tourner à gauche », « tourner à droite »...

La classe Voiture et une instance
La classe Voiture et une instance

Vous apercevez un peu plus loin la voiture de votre voisin garée en face. C'est également un objet de la classe Voiture, avec une marque, une couleur, un nombre de pneus et de sièges, la possibilité d'accélérer, de freiner, de tourner à gauche ou à droite... Seulement, elle n'a ni la même marque, ni la même couleur que la vôtre.

Ces deux objets sont des instances de la classe Voiture.

La voiture de mon voisin est une autre instance
La voiture de mon voisin est une autre instance

L'encapsulation

Vous vous souvenez avoir ouvert le capot de votre voiture après l'avoir garé : vous avez intensément regardé ce qu'il y a à l'intérieur. Malgré votre immense effort de concentration, le fonctionnement du moteur, de tous ces câbles, circuits électriques et autres tuyaux vous échappe encore...

Sous le capot...
Sous le capot...

Fort heureusement, lorsque vous refermez le capot et montez dans votre voiture, vous oubliez toute cette mécanique trop compliquée, et vous conduisez à l'aide d'un volant, de pédales et d'un levier de boîte de vitesse. Grâce à eux, vous pouvez utiliser votre voiture sans être ingénieur en génie mécanique ou électronique ! :)

Votre volant vous facilite bien la tâche...
Votre volant vous facilite bien la tâche...

Imaginez maintenant que vous écriviez une classe très complexe, qui permet de faire plein de choses incroyables ! Malheureusement, personne ne voudra de votre magnifique classe : qui serait assez fou pour se plonger dans votre code et tentez de le déchiffrer ?

Ce à quoi votre code pourrait ressembler...
Ce à quoi votre code pourrait ressembler...

En effet, votre code est un peu comme le bazar qui se trouve sous le capot de votre voiture. Mais vous êtes malins et vous fournissez aux autres développeurs des méthodes très simples et faciles à comprendre, tout en cachant littéralement sous le capot ce qu'elles font, à l'instar du volant, des pédales et du frein à main. Ainsi, les programmeurs qui utiliseront votre classe (y compris vous-mêmes) auront un volant à disposition au lieu d'un moteur et vingt-et-un tuyaux. On appelle ce principe l'encapsulation.

L'héritage

Puis, votre regard se porte sur l'autoroute au loin : vous distinguez d'autres voitures. Mais des formes différentes se déplacent parmi elles : ce ne sont de toute évidence pas des voitures, mais plutôt des camions et des motos. Vous remarquez que ces objets comportent eux aussi des roues ; ils ont eux aussi une couleur et une marque ; ils peuvent eux aussi accélérer, freiner, tourner à gauche, tourner à droite... Ce seraient presque des objets de la classe Voiture.

Une autoroute belge (image de Purka, tirée du site Wikimedia Commons)
Une autoroute belge (image de Purka, tirée du site Wikimedia Commons)

Mince alors ! Il va falloir refaire de nouvelles classes quasiment identiques...
Pourquoi ne pas faire une classe Véhicule plus généraliste, qui décrirait les attributs et méthodes communs aux classes Voiture, Camion et Moto ? C'est une excellente idée !

Notre nouvelle classe Véhicule décrit donc les attributs et les méthodes communs à tous les véhicules routiers, comme le nombre de roues et de sièges, la marque, la couleur, les méthodes « accélérer », « freiner », « tourner à gauche », « tourner à droite »... On l'appelle la classe mère (ou superclasse), par opposition aux classes Voiture, Camion et Moto qui sont ses classes filles (ou sous-classes). On dit également que les classes Voiture, Camion et Moto héritent de la classe Véhicule.

Désormais, inutile de réécrire les attributs et méthodes de la classe Véhicule dans la classe Voiture, car cette dernière hérite des attributs et des méthodes de la classe Véhicule ! :magicien:
Ainsi tous nos objets de la classe Voiture sont également des objets de la classe Véhicule, mais leur description dans la classe Voiture est plus précise (par exemple, les voitures ont un coffre, alors que les camions ont une remorque).

Les trois classes sont des sous-classes de la classe Véhicule
Les trois classes sont des sous-classes de la classe Véhicule

L'un des intérêts de l'héritage est donc de pouvoir créer plusieurs classes différentes dérivant d'une classe-mère sans avoir à recopier les attributs et les méthodes communes dans chaque classe. C'est aussi une façon de penser et concevoir le programme de manière logique et cohérente.

Si nous revenions sur le premier exemple, la classe Fourchette, ainsi que les classes Couteau et Cuillère, sont des sous-classes de la classe Couvert !

Manipuler des objets : les chaînes de caractères

L'horrible secret du type String

Vous souvenez-vous des chaînes de caractères que nous avons vues dans la première partie ?

var coucou:String = "Hello world!";

Regardez bien le type de la variable : String... Il cache un terrible secret : il s'agit en réalité d'une classe !
Et oui ! En écrivant la ligne au-dessus, nous avons sans le savoir, créé une instance de la classe String. Et nous avons également utilisé des propriétés de cette classe ! :waw:

Créer un objet

Tout d'abord, il nous faut apprendre à créer des objets. Il y a une syntaxe particulière à respecter :

new String(); // Je créé un objet de la classe String (je l'ai d'ailleurs créé dans le vide, cette instruction ne servira à rien :D)

Comme vous pouvez le voir, nous utilisons le mot-clé new, suivi du nom de la classe de l'objet que nous voulons créer, et d'éventuels paramètres entre parenthèses (comme pour les fonctions). Par exemple, si nous voulions créer un objet de la classe String contenant la chaîne "Hello world!", nous procéderions ainsi :

var coucou:String = new String("Hello world!"); // Je créé un objet String contenant la chaîne "Hello world!"

Mais, avant nous n'avions pas besoin de new pour faire ça !

Effectivement, la classe String possède une particularité : c'est un type de données. Cela signifie que les objets de cette classe sont un peu spéciaux : ils peuvent agir en tant que simple donnée (nombre, chaîne de caractères, etc.). Ainsi, nous pouvons nous passer de la syntaxe de création d'un objet :

var coucou:String = "Hello world!";

revient à écrire :

var coucou:String = new String("Hello world!");

Qu'en est-il de int, uint et Number ?

Et bien, figurez-vous que ce sont également des classes, qui fonctionnent de la même manière que la classe String !

En effet, ces deux classes sont encore plus spéciales et n'utilisent qu'une seule syntaxe : celle que vous avez apprise dans la première partie du cours. Par contre, la classe Number fonctionne tout à fait normalement, comme la classe String :

var entier:int = new int(-47); // INTERDIT ! ! !
var entier2:int = -42; // Autorisé

var entierNonSigne:uint = new uint(47); // NOOON ! Tout sauf ça !
var entierNonSigne2:uint = 47; // Ouf !

var nombre:Number = new Number(3.1415); // Pas de problème
var nombre2:Number = 3.1415; // Pour les flemmards :D

var monNom:String = new String("Bryan"); // Je sens que je connais cette phrase...
var ouSuisJe:String = "In the kitchen!"; // Argh !

Accéder aux propriétés d'un objet

Reprenons un peu plus de code que nous avons écrit dans la première partie :

var coucou:String = new String("Hello world!");
trace("Cette chaîne contient " + coucou.length + " caractères.");
// Affiche : Cette chaîne contient 13 caractères.

et observons plus particulièrement cette expression : coucou.length.

Nous avons utilisé la propriété length de la classe <minicode type="actionscript"String</minicode> qui renvoie la longueur de la chaîne !
Décortiquons cette instruction :

  • Tout d'abord, nous renseignons le nom de la variable contenant notre objet. Ici, il s'agit de coucou, variable que nous avons déclaré plus haut avec cette ligne : var coucou:String = "Hello world !"..

  • Ensuite, nous utilisons le caractère point « . » pour signaler que nous allons utiliser un attribut ou une méthode de cet objet-là.

  • Enfin, nous spécifions quelle propriété nous voulons utiliser : ici, nous tapons donc length, la propriété de la classe String qui nous intéresse.

Nous obtenons ainsi la longueur de l'objet « chaîne de caractères » contenu dans la variable coucou ! En français, cela donnerait quelque chose comme : « Lis la propriété longueur de l'objet contenu dans ma variable coucou. »

Des pointeurs sous le capot

Plantons le décor

Prenons notre classe Voiture, et supposons qu'elle ait une propriété marque de type String qui contient le nom de la marque des voitures.

Créons un objet de la classe Voiture et spécifions sa marque :

var lienVoiture:Voiture = new Voiture(); // Je créé ma voiture...
lienVoiture.marque = "Peugeot"; // ...de marque Peugeot.

Déclarons une deuxième variable :

var lienVoiture2:Voiture; // Je déclare une autre variable

Ensuite, procédons à une affectation :

lienVoiture2 = lienVoiture; // C'est bien une affectation... Mais que fait-elle réellement ?

Nous allons regarder de quelle marque sont les voitures (vous avez sûrement deviné :D ) :

trace(lienVoiture.marque; // Affiche : Peugeot
trace(lienVoiture2.marque); // Affiche : Peugeot

Bien ! Maintenant, modifions la marque de lienVoiture2 :

lienVoiture2.marque = "Renault";
// Nous pourrions également faire :
lienVoiture2.marque = new String("Renault");

Enfin, regardons à nouveau la marque des voitures :

trace(lienVoiture.marque); // Affiche : Renault
trace(lienVoiture2.marque); // Affiche : Renault

Horreur ! Les deux ont la même marque !
La réponse est simple : il s'agit du même objet ! Et oui, il n'y en a qu'un seul et unique ! :waw:

Explications

Lorsque nous créons l'objet de classe Voiture, il est stocké dans la mémoire vive de votre système. Ensuite, quand nous l'affectons à une variable, un lien vers cet objet est créé, puis stocké dans la variable. On dit alors que les variables sont des pointeurs : elles pointent du doigt l'objet qui leur est associé, afin que nous, programmeurs, puissions accéder à cet objet. D'ailleurs, vous aurez peut-être remarqué le nom précis que j'ai donné à mes variables : lienVoiture et lienVoiture2 ; n'est-ce pas évocateur ? :D

Les variables-pointeurs sont toutes les deux liées à l'objet.
Les variables-pointeurs sont toutes les deux liées à l'objet.

Donc, lorsque nous écrivons notre affectation, nous nous contentons en réalité de recopier le pointeur vers l'objet initialement créé :

lienVoiture2 = lienVoiture; // Recopions le pointeur de lienVoiture dans lienVoiture2

Ainsi, en utilisant les propriétés de l'objet de lienVoiture2, nous utilisons également celles de l'objet de lienVoiture. Logique : il s'agit du même objet !

Et si nous créions un autre objet de classe Voiture ?

Très bonne idée ! Créons un nouvel objet et affectons-le à la variable lienVoiture2 :

lienVoiture2 = new Voiture(); // Un deuxième objet Voiture entre en scène !

Modifions sa marque :

lienVoiture2.marque = "Citroën";

Et regardons la marque des deux voitures :

trace(lienVoiture.marque); // Affiche : Renault
trace(lienVoiture2.marque); // Affiche : Citroën

Ouf ! Quel soulagement ! Nous avons bien deux objets distincts de la classe Voiture !

En résumé
  • Les objets contiennent des propriétés : les variables sont appelées attributs et les fonctions méthodes.

  • Chaque objet est décrit par une classe : il s'agit d'une sorte de plan de construction des objets. On dit que les objets sont des instances (ou occurrences) de leur classe.

  • L'encapsulation est un principe important en POO qui consiste à cacher le fonctionnement interne des classes, et à montrer seulement une interface simplifiée.

  • L'héritage est un autre principe, tout aussi important, consistant à faire hériter des classes (dites classes filles) d'une classe mère.

  • En Actionscript 3, tout est objet : tout ce que vous manipulerez, ce sera des objets.

  • Le mot-clé new permet de créer des objets.

  • La plupart des variables sont en réalité des pointeurs (ou liens) vers des objets stockés en mémoire.

Exemple de certificat de réussite
Exemple de certificat de réussite