UKOnline

Constructeur et variable d'instance

On a vu, dans le chapitre précédent, que le constructeur est appelé lors de la création d'un nouvel objet. Il s'agit en fait d'une méthode particulière dont le code est exécuté lorsqu'une classe est instanciée.

Définition de constructeur

Le constructeur se définit dans une classe comme une fonction avec deux particularités :

  • le nom de la fonction doit être __init__ ;
  • la fonction doit accepter au moins un paramètre, dont le nom doit être self, et qui doit être le premier paramètre.

Le paramètre self représente en fait l'objet cible, c'est-à-dire que c'est une variable qui contient une référence vers l'objet qui est en cours de création. Grâce à ce dernier, on va pouvoir accéder aux attributs et fonctionnalités de l'objet cible.

Modifions la classe Contact en lui ajoutant un constructeur qui permet de créer un nouveau contact en renseignant son prénom, son nom et son numéro de téléphone :

Le constructeur de la classe Contact reçoit donc trois paramètres, en plus du paramètre spécial self, et se contente de les afficher. Lorsqu'on crée une instance de cette classe, il faut donc spécifier des valeurs pour les trois paramètres comme on peut le voir sur la dernière instruction qui crée un objet représentant Brice Thomas.

On peut voir ce qui suit affiché à l'écran après exécution du programme, ce qui témoigne bien du fait que le constructeur a été exécuté :

Brice
Thomas
6942

Référence

Qu'en est-il de la variable brice ? Cette dernière contient tout simplement une référence vers l'objet qui a été créé, c'est-à-dire une indication sur son emplacement en mémoire. On peut observer cela en affichant à l'écran la variable brice, ce qui révèle qu'elle contient une référence vers un objet Contact se trouvant en mémoire à la position 0x10f805c88 :

<__main__.Contact object at 0x10f805c88>

Variable d'instance

La classe Contact, telle qu'elle est pour le moment, n'est pas encore des plus utiles. En effet, il serait souhaitable de pouvoir stocker les informations du contact dans l'objet qui a été créé. On voudrait avoir une situation en mémoire telle que celle présentée à la figure 4, c'est-à-dire avoir des attributs stockant les informations du contact.

Variable d'instance
Un objet de type Contact possède trois attributs représentant respectivement le prénom, le nom et le numéro de téléphone.

Un attribut est représenté par une variable particulière, appelée variable d'instance, accessible à l'aide du paramètre self. L'idée est que le constructeur initialise ces variables d'instances, qui seront alors stockées dans l'objet et en mémoire pour toute la durée de vie de l'objet. On modifie donc le constructeur de la classe Contact en :

Il est important de faire la différence entre les deux types de variables qui se trouvent dans le code de ce constructeur :

  • la variable self.firstname représente la variable d'instance, c'est-à-dire celle associée à l'objet, qui existe à partir de la création de l'objet jusque sa destruction ;
  • la variable firstname représente le paramètre reçu par le constructeur et n'existe que dans le corps de ce dernier.

Le paramètre self permet donc d'accéder aux variables d'instance, c'est-à-dire aux attributs de l'objet cible, depuis le constructeur.

Revenons maintenant à la création d'un objet de type Contact. Puisqu'on a initialisé des variables d'instance dans le constructeur, on va pouvoir y accéder pour n'importe quel objet créé. Si on reprend brice, on va pouvoir afficher la valeur des trois variables d'instance à l'aide de l'opérateur d'accès (.) :

Comme on peut le constater sur le résultat de l'exécution, les valeurs passées en paramètres au constructeur lors de la création de l'objet ont bien été enregistrées dans les variables d'instance de l'objet :

Brice
Thomas
6942

Les variables d'instance sont spécifiques à chaque objet et ce sont d'ailleurs elles qui définissent l'état de l'objet. Pour illustrer cela, voyons un dernier exemple où on crée deux instances de la classe Contact :

La figure 5 montre l'état de la mémoire après exécution de ces deux instructions. On y voit clairement la classe Contact et les deux instances de cette dernière qui ont été créées. Chaque instance possède bel et bien son espace propre en mémoire, où sont stockées les valeurs de ses variables d'instance.

État d'objets
Deux instances d'une même classe occupent deux zones mémoires distinctes déterminant l'identité des objets et dont le contenu définit leur état.

Plusieurs constructeurs

Comme on peut le constater, on a spécifié la valeur $0$ lorsqu'on a créé l'objet représentant Quentin Lurkin. Cela peut, par exemple, signifier que le numéro de téléphone de ce contact n'est pas connu. Il serait dès lors pratique de pouvoir avoir un deuxième constructeur à qui on ne donnerait que le prénom et le nom.

On ne peut pas avoir plusieurs constructeurs dans une classe, mais on peut utiliser la valeur par défaut des paramètres pour arriver à la même fin. Il suffit donc de modifier le constructeur de la classe Contact comme indiqué ci-dessous :

On peut maintenant créer Quentin Lurkin sans spécifier de numéro de téléphone et réécrire l'exemple précédent comme suit :

Pour résumer cette section, le constructeur est donc une méthode particulière qui est exécutée au moment de la création d'un nouvel objet. Son but principal consiste à initialiser l'objet, c'est-à-dire au moins initialiser ses différentes variables d'instance.