Les classes (1ère partie)

Ce contenu est obsolète. Il peut contenir des informations intéressantes mais soyez prudent avec celles-ci.

Dans le chapitre précédent, nous avons introduit la notion de classe, et nous avons même appris à utiliser la classe qu'est String. C'est déjà un bon début dans la découverte de la programmation orientée objet, mais ce n'est pas suffisant. À partir de maintenant, nous allons apprendre à créer nos propres classes. En utilisant le concept d'objets ou de classes, la programmation orientée objet permet d'organiser le code vraiment différemment de la programmation procédurale.

Étant donné qu'il y a beaucoup de choses à dire sur le sujet, la théorie sur les classes s'étalera sur deux chapitres. Nous allons donc voir dans ce chapitre les principes fondamentaux, puis nous complèterons avec quelques notions supplémentaires dans le prochain chapitre.

Créer une classe

La Classe

Rappels

Comme nous l'avons déjà mentionné, une classe est l'ensemble du code permettant de représenter un objet dans un programme. Celle-ci est constituée de variables appelées attributs et de fonctions appelées méthodes. On parle également de propriétés pour définir l'ensemble des attributs et des méthodes d'une classe. Ainsi grâce à ces propriétés, nous allons pouvoir structurer notre objet, et définir l'intégralité de ses caractéristiques.

Une fois que la classe est définie, nous pouvons alors créer des instances ou occurrences de cette classe. Pour vous faire une idée, on peut considérer une instance comme un objet « physique », en opposition à la classe qui définit plutôt une description générale de l'objet. Ainsi nous pouvons créer plusieurs instances d'un même objet, mais dont les caractéristiques pourront varier légèrement.

Il est important de bien faire la différence entre la classe, qui est unique et qui décrit un certain objet, et ses instances qui peuvent être multiples et qui sont les objets « réels ». Ceux-ci peuvent être décrits à partir des mêmes propriétés dont les valeurs peuvent varier.

Pour rassurer tout le monde, nous allons prendre un petit exemple concret :

  • Une classe Voiture permet de définir l'ensemble du parc automobile européen. Cette classe Voiture définit l'ensemble des caractéristiques que peut posséder une automobile. Il serait par exemple possible d'y retrouver la marque de celle-ci, mais également sa couleur ou encore son immatriculation que nous pourrions définir comme attributs.
  • Maintenant nous savons ce qu'est une Voiture, nous aurions peut-être l'envie d'en créer quelques-unes. C'est une très bonne idée, et nous allons commencer par créer une Renault de couleur « grise » et immatriculée dans le « Rhône ». Puis voilà que nous en avons besoin d'une seconde ; très bien, voici une Peugeot de couleur « noire » et immatriculée dans le « Cantal ».

Dans cet exemple, nous avons donc utilisé une classe Voiture pour en créer deux instances qui sont la Renault et la Peugeot.

Structure

Si vous avez bien suivi le deuxième chapitre de la première partie, vous devriez vous rappeler d'un schéma représentant la structure de la classe principale. Je vous propose de généraliser ce schéma et de le compléter un peu plus avec ce que nous venons de découvrir. Notamment nous pouvons y ajouter les attributs et les méthodes. Voici donc comment sont structurées les classes :

Schéma général de la structure d'une classe.

Vous ne devriez donc pas être surpris de la manière dont nous définissons une classe à l'intérieur du code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package
{

    public class NomDeLaClasse
    {
        // Attributs

        // Méthodes

    }

}

Nous allons à présent apprendre à définir chacune des propriétés de la classe !

Construire la classe

Package

Avant toute chose, nous allons brièvement reparler de la notion de package. Nous l'avions défini comme décrivant la position de la classe dans l'arborescence des fichiers de votre projet. Rassurez-vous, c'est toujours le cas ! :lol: Cependant, je voudrais présenter ici la manière à adopter pour positionner ses propres classes dans différents dossiers.

Pour l'instant il est vrai que nous ne disposons pas d'un projet conséquent et que le nombre de classes est assez faible. Cependant lorsque nos projets grandiront et que les classes vont se multiplier, nous devrons faire le tri et ranger nos classes dans différents dossiers afin d'y voir plus clair.

Voici donc un conseil qu'il serait prudent de suivre : organisez vos classes en fonction de leur nature et de leur utilité !

Par exemple nous pourrions imaginer un package nommé vehicules qui contiendrait les classes Voiture, Camion et Moto. Puis nous créons deux nouvelles classes Fourchette et Couteau, qui n'ont apparemment strictement rien à faire dans le package vehicules. Il nous faut alors en insérer un nouveau que nous pourrions nommer couverts.

Attributs

Nous allons maintenant présenter le premier type de propriétés d'une classe : il s'agit des attributs ! Les attributs ne sont en réalité que des variables, nous pouvons donc les déclarer comme n'importe quelle variable :

1
var _unAttribut:String;

Lorsqu'on programme en POO, on a l'habitude de ne pas initialiser les variables lors de la déclaration mais plutôt à l'intérieur d'un constructeur dont nous discuterons un peu après.

Également nous introduisons le mot-clé private devant la déclaration de l'attribut, dont nous reparlerons aussi plus tard :

1
private var _unAttribut:String;

Ça y est, nous avons notre premier attribut !

Par convention en Actionscript 3, nous ajouterons un caractère underscore « _ » devant le nom de tous nos attributs. Cela nous sera pratique lorsque nous écrirons des accesseurs et mutateurs.

Méthodes

Comme nous l'avons précisé plus haut, les méthodes sont des fonctions. Il peut donc s'agir aussi bien d'instructions de fonction que d'expressions de fonction (pour ceux qui auraient tout oublié, allez faire discrètement un tour dans le chapitre sur les fonctions ! :euh: ). Néanmoins je vous avais dit que les instructions de fonction étaient préférables, nous utiliserons donc ce type de fonctions :

1
2
3
4
function uneMéthode():void
{
    // Instructions
}

Bien entendu, à l'intérieur de ces méthodes nous avons accès aux différents attributs afin de pouvoir modifier leur valeur ou simplement lire leur contenu. Au final, seuls les attributs peuvent mémoriser des choses et ainsi se souvenir de l'état de l'objet en question. C'est pourquoi en général vos méthodes serviront à lire ou modifier le contenu d'un ou plusieurs attributs.

Voilà comment notre méthode pourrait modifier un attribut :

1
2
3
4
function uneMéthode(nouvelleValeur:String):void
{
    unAttribut = nouvelleValeur;
}

Bien évidemment nous pouvons faire toutes sortes de manipulations à l'intérieur d'une méthode et pas simplement affecter ou lire le contenu d'un attribut.

Contrairement à d'autres langages, l'Actionscript ne prend pas en compte la surcharge de méthodes. Pour ceux qui découvrent ce terme, nous en reparlerons avant la fin de ce chapitre.

Enfin, les méthodes prennent également un mot-clé devant leur déclaration, qui est cette fois-ci public :

1
2
3
4
public function uneMéthode():void
{
    // Instructions
}

Les mots-clés private et public sont liés à la notion d'encapsulation que nous découvrirons plus en profondeur au cours du chapitre. En attendant, sachez que ces mots-clés existent et considérez qu'ils font partie de la déclaration des propriétés d'une classe.

Constructeur

À présent il est temps d'introduire une méthode un peu particulière : le constructeur ! Le constructeur est la méthode appelée par défaut lors de l'initialisation d'un objet ; vous savez lorsque vous utilisez le mot-clé new. Vous noterez que cette méthode possède obligatoirement le même nom que celui de la classe. Par exemple pour notre classe nommée Voiture, notre constructeur pourrait ressembler à ceci :

1
2
3
4
public function Voiture()
{
    // Instructions
}

Le constructeur d'une classe sert principalement à initialiser l'ensemble des attributs déclarés dans celle-ci.

Vous remarquerez que le constructeur ne peut pas renvoyer de valeur, aussi évitez d'insérer le mot-clé return à l'intérieur de celui-ci. Une instruction de renvoi serait ignorée à l'exécution, et pourrait entraîner des messages d'erreur lors de la compilation.

Ne vous inquiétez pas si certains points sont encore flous dans votre esprit, nous créerons une classe pas à pas à la fin du chapitre !

Des paramètres facultatifs pour nos méthodes

La surcharge de méthodes

Dans beaucoup de langages utilisant la programmation orientée objet, on retrouve le concept de surcharge de méthodes, mais ce n'est pas le cas en ActionScript 3. Contrairement à son nom abominable, ce concept est relativement simple et consiste a définir plusieurs méthodes portant le même nom. Il est alors possible de définir des paramètres de types différents ou encore d'utiliser un nombre de paramètres différent. Ceci est très utile et permet par exemple de définir plusieurs constructeurs n'ayant pas le même nombre de paramètres :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package
{

    public class MaClasse
    {
        // Attribut
        private var _unAttribut:int;

        // Constructeurs
        public function MaClasse()
        {
            _unAttribut = 0;
        }

        public function MaClasse(entier:int)
        {
            _unAttribut = entier;
        }

    }

}

Dans l'exemple précédent, il serait possible d'instancier une classe sans renseigner de paramètres avec le premier constructeur, ou en précisant la valeur de l'entier avec le second. Cette technique servirait donc à rendre l'utilisation d'une classe plus simple et plus souple, en permettant l'appel « d'une même fonction » avec des paramètres différents.

Malheureusement donc, la surcharge de méthodes est strictement interdite en Actionscript, vous ne trouverez donc jamais deux méthodes ayant le même nom au sein d'une classe, et ceci est aussi valable pour les constructeurs. En revanche il est possible de contourner le problème, voire même de le simplifier : la définition de paramètres facultatifs !

Les paramètres facultatifs

Définition

Comme nous l'avons déjà dit, la surcharge de méthodes est interdite en Actionscript ! C'est un point important, c'est pourquoi ce n'est pas superflu de le redire une nouvelle fois. En revanche en Actionscript il existe un concept qui permet d'obtenir une utilisation similaire. Il s'agit de paramètres facultatifs ! Cette nouvelle notion est associée en réalité à la définition de fonctions et n'est donc pas limitée qu'aux méthodes. Ainsi pour insérer un paramètre facultatif, il suffit de lui préciser une valeur par défaut dans lors de la définition de la fonction, comme ceci :

1
2
3
4
function maFonction(entier:int, texte:String = "Valeur par défaut", nombre:Number = 0):void 
{ 
    trace(nombre, texte); 
}

En utilisant ici des valeurs par défaut pour les deux derniers paramètres, il alors possible de les « omettre » lors de l'appel de la fonction. Ainsi contrairement à la surcharge de méthode, nous n'avons pas besoin en Actionscript de réécrire l'intégralité du contenu de la fonction pour chaque définition de nouveaux paramètres.

Attention cependant à l'ordre de définition des paramètres ; les paramètres facultatifs doivent obligatoirement être placés à la fin de la liste des paramètres. Également, ils doivent être écrits dans un ordre d'utilisation précis que nous allons préciser en parlant des appels de ces fonctions.

Appels

Comme leur nom l'indique, les paramètres facultatifs peuvent être « omis » lors de l'appel de la fonction. Ainsi la fonction définie précédemment, peut être appelée en renseignant uniquement le premier paramètre :

1
maFonction(10);

Il est également possible de renseigner les deux premiers paramètres, sans le troisième :

1
maFonction(10, "Nouveau texte");

Attention toutefois à l'ordre de définition des paramètres facultatifs. En effet, s'il est possible de renseigner le premier paramètre facultatif et d'omettre le second, l'inverse n'est pas possible. Ainsi l'appel suivant n'est pas correct : maFonction(10, 5). C'est pourquoi vous devez être vigilent dans l'ordre de définition des paramètres facultatifs de vos fonctions !

Enfin pour finir, voici dernier appel possible de votre fonction, qui comprend l'intégralité des paramètres :

1
maFonction(10, "Nouveau texte", 5);

Ainsi grâce à la définition de paramètres facultatifs, nous avons trois manières différentes d'appeler la même fonction !

Encapsulation

L'encapsulation que nous allons redécouvrir maintenant est l'un des concepts les plus importants de la programmation orientée objet ! Vous rappelez-vous du mot-clé private que nous avons introduit avant chacun de nos attributs ? Il permet de masquer la propriété à laquelle il est associé ; celle-ci n'est donc pas visible depuis l'extérieur de la classe en question. Ainsi à partir de maintenant, nous masquerons obligatoirement l'ensemble de nos attributs ! Pour y accéder, nous serons donc dans l'obligation de faire appel à une méthode intermédiaire qui nous permettra de vérifier les données et d'affecter les attributs en conséquence, hors du champ de vision de l'utilisateur.

L'intérêt de l'encapsulation est de simplifier l'utilisation des objets en masquant l'ensemble des attributs et des méthodes qui sont utiles simplement au fonctionnement de l'objet. Ainsi, vu de l'extérieur, nous pourrons manipuler ces objets facilement, sans nous soucier de leur fonctionnement interne.

Ce concept introduit donc la notion de droits d'accès que nous allons voir tout de suite !

Les différents droits d'accès

Il n'est pas possible de parler d'encapsulation sans toucher un mot des droits d'accès ou portées. Ces droits d'accès définissent la visibilité d'une propriété au sein de votre code. En Actionscript, il existe trois portées qui sont public, private et internal. Ces mots-clés se placent juste avant la déclaration des propriétés auxquelles ils sont associés.

En réalité, il existe une quatrième portée nommée protected. Cependant celle-ci est profondément liée à la notion d'héritage dont nous reparlons dans un chapitre qui lui est consacré.

Privés

Les droits d'accès dits « privés » s'utilisent avec le mot-clé private. Ils permettent de restreindre l'utilisation de la propriété à la classe où elle est définie. Ainsi cette propriété ne sera pas visible depuis l'extérieur de cette classe. Voici un attribut dont la portée est de type private :

1
private var _monAttribut:String;

Je rappelle que tous nos attributs doivent être invisibles depuis l'extérieur de la classe où ils sont définis, utilisez donc la portée private.

Publiques

Les droits d'accès « publiques » sont associés au mot-clé public, que nous avons déjà croisé plusieurs fois. Celui-ci permet de rendre visible partout dans le code la propriété à laquelle il est associé. Ce sera donc le cas pour la majorité de vos méthodes. D'ailleurs, il est impossible d'affecter une autre portée que public à un constructeur :

1
2
3
4
public function MonConstructeur():void 
{
    ...
}

Internes

Les droits d'accès « internes » sont un peu spéciaux ; ils sont associés au mot-clé internal. Les propriétés définies avec ce type de portées sont visibles depuis l'ensemble du package, dont la classe où elle est déclarée appartient.

1
internal var _monAttribut:int;

Cette portée n'est pas très utilisée en général, mais sachez qu'il s'agit de la portée par défaut lorsqu'aucune autre n'est spécifiée.

Les accesseurs

Syntaxe

Il existe un type de méthodes un peu spécial, qui est directement lié à la notion d'encapsulation : les accesseurs ! En réalité, on désigne par accesseurs l'ensemble des accesseurs et mutateurs, également appelées getters et setters. Ceux-ci permettent l'accès direct à un attribut de portée private en lecture par l'accesseur et en écriture par le mutateur. Ainsi dans beaucoup de langages de programmation, on retrouve un ensemble d'accesseurs dont le nom débute par get (de l'anglais to get qui signifie « obtenir ») et un ensemble de mutateurs dont le nom débute par set (de l'anglais to set qui signifie « définir »).

Pour gérer l'ensemble des accesseurs, l'Actionscript a introduit deux mots-clés get et set qui permettent notamment de donner un nom identique aux deux accesseurs. Pour illustrer ça d'un exemple, voici un attribut quelconque dont la portée est de type private :

1
private var _texte:String;

Étant donné que cet attribut est de type private, il n'est pas accessible depuis l'extérieur de la classe où il a été défini. Cependant, il est probable que nous ayons besoin de modifier cet attribut depuis la classe principale. Si nous voulons respecter le concept d'encapsulation, nous devons donc conserver la portée de cet attribut et définir des accesseurs pour y avoir accès :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Accesseur
public function get texte():String
{
    return _texte;
}

// Mutateur
public function set texte(nouveauTexte:String):void
{
    _texte = nouveauTexte;
}

Comme vous le voyez, mes deux accesseurs utilisent le même nom de fonction, ce qui est drôlement pratique. Mais l'utilisation des accesseurs va plus loin que ça, car leur utilisation est un peu particulière. Ainsi l'accesseur get d'une instance nommée MonObjet s'utilise sans les parenthèses :

1
var maVariable:String = MonObjet.texte;

Quant à lui, le mutateur s'utilise également sans parenthèses, mais avec le symbole égal « = » qui est considéré comme un signe d'affectation :

1
MonObjet.texte = "Nouvelle chaîne de caractères";

Une telle utilisation des accesseurs est spécifique à l'Actionscript. Cette technique permet de manipuler les accesseurs comme s'il s'agissait de l'attribut lui-même. Cependant en utilisant les getters et setters, vous respectez le concept d'encapsulation. Ainsi, les propriétés créées à partir d'accesseurs sont considérées comme étant des attributs, et non des méthodes.

Une raison supplémentaire d'utiliser les accesseurs

Lorsque vous utilisez des accesseurs, vous n'êtes pas obligés de vous contenter de lire un attribut dans un getter ou de lui affecter une nouvelle valeur dans un setter : en effet, il est tout à fait possible d'ajouter du code supplémentaire, voire de ne pas manipuler d'attribut en particulier !

Prenons la classe suivante :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package  
{
    /**
     * Une classe d'exemple
     */
    public class Voiture
    {
        private var _largeur:int;

        public function Voiture() 
        {

        }

        public function get largeur():int 
        {
            return _largeur;
        }

        public function set largeur(value:int):void 
        {
            _largeur = value;
        }

        public function mettreAJour():void
        {
            // Mettre à jour l'affichage
        }
    }

}

Dans un premier temps, imaginons que dans notre classe, nous disposions d'une méthode mettreAJour() qui met à jour l'affichage de notre objet en fonction de la valeur de l'attribut _largeur. Pour spécifier la largeur de la voiture, nous procéderions ainsi :

1
2
3
4
5
var voiture:Voiture = new Voiture();
voiture.largeur = 100; // Largeur de la voiture
voiture.mettreAJour(); // Mettons à jour l'affichage de la voiture pour une largeur de 100
voiture.largeur = 150; // Changeons la largeur de la voiture
voiture.mettreAJour(); // Mettons à jour l'affichage de la voiture pour une largeur de 150

Grâce aux accesseurs, il est possible de l'appeler automatiquement dès que l'on modifie la largeur de l'objet :

1
2
3
4
5
public function set largeur(value:int):void 
{
    _largeur = value;
    mettreAJour();
}

Ainsi, au lieu d'avoir à appeler manuellement la méthode mettreAJour(), il suffit de modifier la largeur :

1
2
3
4
5
var voiture:Voiture = new Voiture();
voiture.largeur = 100; // Largeur de la voiture
// L'affichage de la voiture  est automatiquement mis à jour dans l'accesseur set largeur !
voiture.largeur = 150; // Changeons la largeur de la voiture
// Encore une fois, l'affichage de la voiture  est automatiquement mis à jour, il n'y a rien d'autre à faire !

Maintenant, nous aimerions limiter les valeurs possibles de l'attribut largeur ; disons qu'il doit être supérieur à 100 et inférieur à 200.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var voiture:Voiture = new Voiture();
voiture.largeur = 100; // Largeur de la voiture
// On vérifie que la largeur est dans les limites
if(voiture.largeur < 100)
{
    voiture.largeur = 100;
}
else if(voiture.largeur > 200)
{
    voiture.largeur = 200;
}
trace(voiture.largeur); // Affiche: 100

voiture.largeur = 250; // Changeons la largeur de la voiture
// On vérifie une fois de plus que la largeur est dans les limites
if(voiture.largeur < 100)
{
    voiture.largeur = 100;
}
else if(voiture.largeur > 200)
{
    voiture.largeur = 200;
}
trace(voiture.largeur); // Affiche: 200

Vous remarquerez que c'est plutôt fastidieux. Bien sûr, nous pourrions utiliser une fonction, mais il vaut mieux mettre dans la classe Voiture ce qui appartient à la classe Voiture ! ^^ Encore une fois, les accesseurs nous facilitent grandement la tâche ; voyez plutôt :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public function set largeur(value:int):void 
{
    _largeur = value;

    // _largeur doit être comprise entre 100 et 200
    if (_largeur < 100)
    {
        _largeur = 100;
    }
    else if(_largeur > 200)
    {
        _largeur = 200;
    }

    mettreAJour();
}

Le code principal serait alors écrit ainsi :

1
2
3
4
5
6
7
var voiture:Voiture = new Voiture();
voiture.largeur = 100; // Largeur de la voiture
// Plus besoin de vérifier que la largeur est dans les limites, l'accesseur le fait pour nous !
trace(voiture.largeur); // Affiche: 100

voiture.largeur = 250; // Changeons la largeur de la voiture
trace(voiture.largeur); // Affiche: 200

Avouez que c'est extrêmement pratique ! Je vous conseille d'appliquer cette façon de faire le plus souvent possible, cela vous rendra service. ;)

Générateur de code dans Flashdevelop

Il existe un outil très pratique disponible dans la plupart des IDE, dont Flashdevelop, pour générer automatiquement des portions de codes. Nous pouvons l'utiliser, entre autres, pour générer les accesseurs de nos attributs ! Pour cela, il faut suivre trois étapes :

1. Placer le curseur sur la ligne de l'attribut dont il faut générer les accesseurs

2. Sélectionner l'option 'Code Generator'

3. Sélectionner une des trois options

Il est également possible de se passer de la deuxième étape en utilisant directement le raccourci Ctrl + Maj + 1.

Le code ainsi généré, ressemblera à ceci :

1
2
3
4
5
6
7
8
9
public function get texte():String 
{
    return _texte;
}

public function set texte(value:String):void 
{
    _texte = value;
}

Exercice : Créons notre première classe

Présentation de la classe

Description

Afin de mieux comprendre tout ceci, nous allons maintenant écrire notre première classe pas à pas ! Nous allons donc créer une classe Voiture, que je vous propose de découvrir maintenant. Nous y intégrerons les attributs suivants, ainsi que les accesseurs correspondants :

  • saMarque : cet argument de type String permet de définir la marque de la voiture. Celui-ci sera défini dans le constructeur et il s'agit du seul attribut qui ne possèdera pas de mutateur. En effet, une voiture peut être repeinte, modifiée par divers « accessoires » qui influeront sur sa longueur ou encore elle peut changer de plaque d'immatriculation. En revanche, elle ne peut pas changer sa marque de fabrique.
  • saCouleur : cet argument de type String représente la couleur de peinture de la voiture. Celle-ci sera manipulée par les deux accesseurs nommés couleur.
  • saLongueur : la longueur du véhicule sera définie par une variable de type int. Deux accesseurs longueur permettront de manipuler cet élément. Lors d'une affectation, nous devrons vérifier si la valeur renseignée est positive. Dans le cas contraire, nous utiliserons la valeur -1 pour préciser que la longueur est « non renseignée ».
  • sonImmatriculation : enfin l'immatriculation du véhicule sera stockée dans un attribut de type String, qui possèdera deux accesseurs immatriculation.

Lançons-nous donc dans la conception de cette classe. Lisez avec attention, afin de noter les différentes étapes de création d'une classe.

UML : Unified Modeling Language

Lorsqu'on programme, il est possible de représenter les différentes classes sur un schéma pour « résumer » leurs propriétés. Il existe différentes modélisations standards dont l'Unified Modeling Language ou UML. Cette représentation est très souvent associée aux langages orientés objets comme l'Actionscript. Sans donner plus de détails, je vous propose de découvrir la représentation correspondant à notre classe Voiture :

Représentation UML de la classe Voiture

Comme vous le voyez, notre classe est divisée en deux parties : les attributs et les méthodes ! Ceux-ci sont donc listés en spécifiant de quels types ils sont, ainsi que les paramètres à renseigner en ce qui concerne les méthodes. Cela permet de dresser une sorte de « plan de construction » de la classe à coder, mais également son mode d'emploi pour d'éventuels autres programmeurs. Cela permet également de mettre en évidence les relations liant les classes les unes aux autres, comme nous le verrons au cours des chapitres à venir. Vous aurez très certainement remarqué les signes « - » et « + » qui précèdent l'ensemble de nos propriétés. Ceux-ci permettent de représenter les différents droits d'accès liés à chacune de nos propriétés de la manière suivante : « - » pour privés, « + » pour publiques, « ~ » pour internes et « # » pour protégés.

L'objectif du cours n'est pas de vous apprendre à utiliser l'UML, cependant nous utiliserons quelques schémas qui sont souvent plus clairs que des mots. Vous apprendrez à lire et utiliser les bases de cette modélisation au fil des chapitres de cette partie.

Écriture du code

Préparation du nouveau fichier

Tout d'abord, pour créer une nouvelle classe, nous aurons besoin d'un nouveau fichier Actionscript ! Nous allons donc insérer une classe nommée Voiture avec File > New > AS3 Document si vous êtes sous FlashDevelop ou créer un nouveau fichier nommé Voiture.as si vous n'utilisez pas ce logiciel.

Puis, nous insèrerons à l'intérieur le code de définition de la classe, comme ceci :

1
2
3
4
5
6
7
8
package
{
    public class Voiture
    {

    }

}

Déclaration des attributs

Précédemment, nous avons défini les quatre attributs qui sont saMarque, saCouleur, saLongueur et sonImmatriculation. Tous ces attributs ont évidemment des droits d'accès de type private, pour respecter le concept d'encapsulation.

Voici donc les différentes déclarations d'attributs :

1
2
3
4
private var _marque:String;
private var _couleur:String;
private var _longueur:int;
private var _immatriculation:String;

Le constructeur

Comme nous l'avons rapidement introduit, le constructeur de cette classe devra recevoir en paramètre la marque de fabrication du véhicule. Sachant que les autres attributs possèdent des setters, nous ne les introduirons pas dans la liste des paramètres à spécifier au constructeur. Néanmoins, ceux-ci devront tout de même être initialisés.

Il est recommandé d'utiliser dès que cela est possible les accesseurs et les mutateurs au sein même de la classe ; exception faite du constructeur, où cela n'est généralement pas nécessaire.

Découvrons tout de suite ce constructeur :

1
2
3
4
5
6
7
public function Voiture(marque:String)
{
    _marque = marque;
    _couleur = "Sans couleur";
    _longueur = -1;
    _immatriculation = "Non immatriculée";
}

Vous pouvez utiliser des noms de paramètres identiques aux noms de vos propriétés (ici marque) : ils sont en effet prioritaires. Pour pouvoir utiliser explicitement une propriété de l'objet, il faut ajouter le mot-clé this devant : si nous avions un mutateur pour l'attribut marque, nous devrions écrire this.marque = marque; pour l'utiliser.

Les accesseurs

Chaque attribut possède un ou deux accesseurs, nous ne les détaillerons donc pas tous. Je vous propose plutôt de découvrir un getter et un setter. Nous allons prendre l'exemple des accesseurs longueur, dont voici le getter :

1
2
3
4
public function get longueur():int
{
    return _longueur;
}

Cet accesseur n'a rien de très compliqué, nous n'en parlerons donc pas plus. En revanche pour le mutateur, nous devons vérifier si la valeur spécifiée est positive, je vous rappelle. Nous devrons donc utiliser une condition en if...else pour faire la vérification.

Voici donc le mutateur en question, que vous êtes normalement en mesure de comprendre par vous-mêmes maintenant :

1
2
3
4
5
6
7
public function set longueur(nouvelleLongueur:int):void
{
    if(nouvelleLongueur > 0)
        _longueur =  nouvelleLongueur;
    else
        _longueur =  -1;
}

Félicitations, nous avons terminé l'écriture de votre première classe !

La classe complète

Parce qu'il est probable que certains ne soient pas pleinement satisfaits avant d'avoir vu l'intégralité de celle-ci, je vous propose ici un récapitulatif intégral de la classe Voiture :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package
{
    public class Voiture
    {
        /*************** Attributs ***************/
        private var _marque:String;
        private var _couleur:String;
        private var _longueur:int;
        private var _immatriculation:String;

        /************* Constructeur *************/
        public function Voiture(marque:String)
        {
            _marque = marque;
            _couleur = "Sans couleur";
            _longueur = -1;
            _immatriculation = "Non immatriculée";
        }

        /*************** Accesseurs ***************/
        public function get marque():String
        {
            return _marque;
        }

        public function get couleur():String
        {
            return _couleur;
        }

        public function get longueur():int
        {
            return _longueur;
        }

        public function get immatriculation():String
        {
            return _immatriculation;
        }

        /*************** Mutateurs ***************/
        public function set couleur(nouvelleCouleur:String):void
        {
            _couleur = nouvelleCouleur;
        }

        public function set longueur(nouvelleLongueur:int):void
        {
            _longueur = (nouvelleLongueur > 0) ? nouvelleLongueur : -1;
        }

        public function set immatriculation(nouvelleImmatriculation:String):void
        {
            _immatriculation = nouvelleImmatriculation;
        }

    }

}

Voiture


En résumé

  • Le mot-clé this fait référence à l'objet lui-même.
  • Les classes sont triées dans différents package en fonction du type d'objets qu'elles représentent.
  • Le constructeur est une méthode particulière appelée à la création d'une instance, où on initialise généralement les attributs.
  • Il est possible de définir des paramètres facultatifs à l'intérieur de nos fonctions et méthodes, pour palier l'impossibilité de surcharger celles-ci.
  • L'encapsulation est le concept permettant de masquer le fonctionnement interne d'une classe.
  • Pour gérer les droits d'accès, nous disposons des différents mots-clés public, private, internal et protected (que nous aborderons plus loin).
  • Des accesseurs peuvent être déclarés à l'aide des mots-clés get et set, et simplifient l'accès aux attributs d'une classe.