Le deuxième concept fondamental de la programmation est celui du variable.


Variables, données, data, valeurs, information, contenus

Définition : une variable est une donnée, elle contient de l’information. Autremment dit, une variable contient une valeur quelconque (5, 13, 666, "Hello World!", 3.145, etc). Cette variable est identifiée par un nom sans espaces (x, y, premiereCouleur, deuxiemeCouleur, etc). Chaque fois que vous utilisez ce mot, vous utiliserez sa valeur interne.


Nous utilisons tous les jours des variables sur un ordinateur sans forcément le savoir. La position de la fenêtre de votre navigateur (celui que vous utilisez pour lire cette page) est définie par un variable. Le texte que cette page contient est également une variable : une longue variable qui contient tous les caractères du texte. Et chacune des images sur cette page est également contenue à l’intérieur de variables. Des variables sont partout dans les programmes informatiques.

Comme dans notre concept précedent, nous avons déjà eu affaire à une variable : mouseX et mouseY. Chaque fois que nous tapons l’expression mouseX dans notre programme, le processeur va chercher la valeur actuelle de la position horizontale de la souris et utilisera cette valeur à la place du mot mouseX. Là où nous voyons un mot, l’ordinateur voit un chiffre. Du coup, on peut remplacer un chiffre fixe dans une méthode qui demande un chiffre, et plus précisément par un chiffre qui varie, d’où le terme “variable”.

Dans cet exemple du chapitre précédent, nous voyons qu’au lieu de taper l’expression line(50,50,150,175), ou quelque chose dans le genre, nous avons remplacé les deux chiffres fixes (150 et 175) par des chiffres variables (mouseX et mouseY).

mais ce serait très limité si Processing devait imaginer toutes les variables dont on aurait besoin. C’est justemment pour cette raison que nous pouvons, nous aussi, créer des variables. mais c’est aussi avec cette possibilité que les choses se compliquent un peu. Tenez-vous bien, réspirer un bon coup, et plongeons nous dans la vie des variables…

Pour créer une variable, il faut d’abord la définir. Lors de cette définition, il faut déclarer le type de votre variable. Pour des raisons techniques, un ordinateur a besoin de savoir combien de place chaque variable prendra, et c’est à la définition de notre variable que nous allons lui dire combien de place il nous faudra. D’habitude votre programme contiendra deux types de variables : des numéros entiers et des numéros à virgule. Les numéros entiers sont appelés des integers en anglais, qui s’écrit dans Processing avec l’expression int. Les numéros à virgule sont appelés des floating-point numbers, ou float dans le langage de Processing.

Commençons avec un exemple. Voici le code qu’il faut écrire dans Processing :


int entier;
float avecVirgule;

entier = 1;
avecVirgule = 2;

println(entier);
println(avecVirgule);

Et son résultat lorsque vous appuyez sur le bouton lecture :

Notez d’abord que nous avons largement simplifié notre exemple en enlevant toute méthode de notre programme : les expressions sont traitées les unes après les autres, ce qui simplifie la compréhension du programme. Ensuite, notez que nous avons défini deux variables, une première de type int et le deuxième de type float. Nous avons ensuite affecté deux valeurs à ces variables : entier = 1; et avecVirgule = 2;. mais quand nous appuyons sur lecture nous constatons qu’un des variables a changé notre valeur : au lieu d’afficher le valeur de départ 2, il l’a transformé en 2.0.

En plus, si nous essayons d’aller dans l’autre sens, à savoir donner une valeur de type float à une variable de type entier, Processing nous donne carrément une erreur :

Visiblement Processing n’est pas très content. mais heureusement, Processing fait l’effort de nous décrire le problème : en anglais, il indique que la valeur à droite du signe = est de type float et ne peut pas être affectée à la variable à gauche, de type int.

Apparement, le processeur (l’ordinateur, si vous voulez) arrive assez facilement à ajouter un .0 à une valeur de type int, mais n’arrive pas à forcer une valeur de type float dans une variable de type int. Si on voulait faire ceci, il faudrait en réalité écrire le programme suivant :


int entier;
float avecVirgule;

entier = (int) 1.8;
avecVirgule = 2.0;

println(entier);
println(avecVirgule);

Ce qui donnera le résultat suivant :

En écrivant (int) avant notre valeur de type float, nous forçons la valeur 1.8 à enlever la valeur après la virgule, et ne garder que la valeur 1 d’avant la virgule. Cette transformation peut être très pratique pour vous pour la suite.

Variables, version pratique

Nous venons de voir que les variables doivent être définies, et qu’elle doivent être définies dès le départ avec leur type. Regardons maintenant comment on se sert de ces variables dans nos programmes.

On peut utiliser un variable à l’intérieur de plusieures choses, mais pour l’instant on va parler de trois types d’uages :

  • des variables à l’intérieur d’une méthode
  • des variables utilisables de façon globale à l’intérieur de toutes les méthodes
  • des variables qui sont “passées” à une méthode (à l’intérieur de ses parenthèses)

Commençons par le premier. Dans l’exemple suivant, nous allons définir une variable qui va récupérer la valeur de la souris, enlèvera cette valeur de la valeur 200, pour ensuite l’appliquer dans le positionnement d’une ellipse :


void setup() {
  size(200,200);
}

void draw() {

  int x;

  background(255);

  x = 200 - mouseX;
  ellipse(x,mouseY,50,50);
}

Dans cet exemple nous voyons qu’à chaque execution de la méthode draw( ) le processeur définit une nouvelle variable de type int, donne une nouvelle valeur à cette variable (200 - mouseX), puis utilise cette variable dans le positionnement de notre ellipse. A la fin de chaque execution de la méthode draw( ), notre variable disparaîtra de la mémoire de l’ordinateur. Notez également que nous avons utilisé directemment la valeur de la variable mouseY, sans la modifier avec une variable intermédiare. C’est pour cette raison que l’ellipse suit la position verticale, mais s’inverse sur le plan horizontal.

Si nous voulons que notre variable soit utilisable pour tout le programme, et qu’elle ne disparaîsse pas entre chaque execution de la méthode draw( ), nous allons devoir la déclarer comme une variable globale, c’est-à-dire en début du programme avant toutes les méthodes :


int largeur; // varaible globale

void setup() {
  largeur = 200; // donner une valeur à notre variable
  size(largeur, 200);
}

void draw() {

  int x;

  background(255);

  x = largeur - mouseX; // utiliser notre variable
  ellipse(x,mouseY,50,50);
}

Une fois que notre variable est définie en début du programme, elle devient accessible à toutes les méthodes contenues dans ce programme. Elles peuvent lui donner de nouvelles valeurs, elles peuvent faire des additions, soustractions, multiplications, divisions, etc, à cette variable pour ensuite s’en servir à l’intérieur de la méthode. La valeur sera respecté entre une méthode et une autre, parce que la variable fait maintenant partie de la mémoire de l’ordinateur (et jusqu’à ce qu’on arrête le programme).

Nous allons maintenant terminer notre tour rapide de l’usage des variables, avec sa forme la plus complexe (mais très puissante).

  • Avez-vous remarqué qu’avec chaque méthode, nous avons deux signes étranges : le void et les parenthèses vides ( )? Savez-vous à quoi servent ces deux élements?

Lisez le programme suivant et essayez de comprendre ce qui se passe (nous avons ajouté quelques commentaires pour vous aider) :


void setup() {
  size(200, 200);
}

void draw() {

  // déclarer deux variables temporaires (utilisables dans cette méthode)
  int x, y;
  // prêter ces deux valeurs à une autre méthode, récupérer le résultat
  x = inverser(mouseX, 200);
  y = inverser(mouseY, 200);
  // effacer la fenêtre
  background(255);
  // dessiner une ellipse avec nos deux valeurs pour les positions h/v
  ellipse(x,y,50,50);

}

int inverser(int valeur, int limite) { // récupérer deux variables, rendre une autre

  // déclarer une variable temporaire
  int resultat;
  // calculer le resultat
  resultat = limite - valeur;
  // rendre à celui que a appelé cette méthode, le résultat
  return(resultat);

}

Ce programme est complexe, soit, mais il a l’avantage d’enfin nous expliquer l’histoire du void et les parenthèses vides ( ).

On pourrait presque dire qu’une méthode une sorte d’usine. Elle peut prendre des données, traiter ces données, et donner le resultat en retour. C’est un principe très puissant de la programmation : la possibilité de prendre beaucoup de choses complexes et les enfermer dans une boîte noire qui nous cache toute cette complexité. Par exemple, nous ne savons pas tous les details de comment Processing arrive à dessiner une ligne sur un écran : on veut juste lui donner les points de notre ligne et qu’il nous la dessine. C’est pareil pour n’importe quel programme : les méthodes sont des assistants, des boîtes noires, bref des usines où on peut traiter des choses complexes de façon simple, avec un mot magique suivi de quelques paramètres.

mais pour avoir cette usine, il faut avoir un moyen de passer à l’usine des valeurs, des paramètres, c’est-à-dire des spécificités de comment on veut dessiner la ligne ou colorer le carré. Il faut aussi avoir un moyen — comme dans le cas de notre code d’inversement — pour que notre usine nous traite nos paramètres et nous donne un résultat.

Dans les deux cas — 1) l’entrée des paramètres dans la boîte noire et 2) la récupération du résultat — il nous faut une variable. Et comme pour n’importe quelle variable, il faut donner le type de la variable, à la fois pour les paramètres et pour la valeur de retour :

Quand on appelle la méthode inverser( ), on lui “passe” deux valeurs : mouseY et 200. La méthode prend ces deux valeurs et les mets à l’intérieur des deux variables respectives : valeur et limite. A l’intérieur de la méthode, elle se sert des ces valeurs comme n’importe quelle variable. Par exemple, ici, elle soustrait la valeur de l’une (valeur) de l’autre (limite). Ensuite, le résultat de cette soustraction (la variable resultat) est repassé à la ligne qui a appelé la méthode, et elle est utilisé pour affecter la valeur de la variable y.

Dans notre exemple, notre “usine” s’appelle inverser( ) et donne en retour un resultat de type int. C’est pour cette raison que nous écrivons int inverser( ) : parce que la méthode donne en retour (return</code) une valeur de ce type. Par contre, dans les exemples précédents, comme par exemple pour la méthodefaireUnTruc( )nous n'avions pas besoin d'une valeur de retour, d'où le motvoidjuste devant la méthode :void faireUnTruc( ) { … }. Les motsint,float, ouvoid““ explique le type de valeur de retour d’une méthode, voire si la méthode a même une valeur à donner en retour.

Résumé

Nous avons vu qu’une variable sert à créer une donnée (une valeur quelconque) et à pouvoir se servir de cette donnée dans notre programme. Nous avons vu que les variables peuvent : venir de Processing lui-même (comme dans le cas de mouseX); être créées à l’intérieur des méthodes; être définies en début du programme (variables globales); ou être “passées” comme paramètre à l’intérieur de la définition d’une méthode. Nous avons également vu que chaque variable doit être définie par son type (nous n’avons vu, pour l’instant, que les types int et float).

Il est intéressant de noter que nous avons déjà commencé à mélanger les deux premiers concepts de programmation : méthode et variable, surtout dans le cas de passage des variables à l’intérieur des parenthèses d’une méthode. Ce genre de mélange des concepts se fera de plus en plus que nous avançons dans les quatre concepts.

Exercise

Comme pour le cours précédent, prennez un de vos programmes existant, mais cette fois-ci ajouter quelques variables supplémentaires. Essayez également (optionnel) de créer une méthode-usine, qui traitera un chiffre quelconque en donnant une valeur de retour.