GWC – Semaine 11 – Les objets

Cet article se base sur celui de Daniel Shiffman.

Les objets

Avant de commencer à connaître comment la programmation orientée objet (POO) fonctionne, commençons par une histoire sur les objets en soi. Imaginez que vous ne programmez pas, mais qu’au lieu vous rédigez le programme de votre journée soit les instructions. Cela pourrait ressembler à quelque chose du genre :

  • Se réveiller
  • Boire du café
  • Manger un déjeuner : oeufs, rôties et bacon
  • Conduire la voiture

Qu’est-ce qui est impliqué dans cette liste? Spécifiquement, quels sont les éléments qui sont impliqués? Premièrement, même si cela n’est pas évident de la manière que l’on a écrit ces instruction, l’élément primaire est vous, un humain, une personne. Vous affichez certaines propriétés. Vous avec une certaine apparence, peut-être que vous avez des cheveux noirs, portez des lunettes et avez l’air un peu intello. Vous avez les capacités de faire des choses comme vous réveiller (et dormir évidemment), manger ou conduire la voiture. Un objet est comme vous, une chose qui a des propriétés et qui peut faire des choses.

Alors, comment peut-on relier cette journée à la programmation? Les propriétés d’un objet sont des variables et les choses qu’un objet peut faire sont des fonctions. La programmation orientée objet est le mariage de toutes les notions fondamentales de la programmation soit les données et les fonctionnalités.

Prenons le temps de décrire les données et les fonctions d’un objet humain très simple :

Données humaines
  • Taille
  • Masse
  • Sexe
  • Couleur des yeux
  • Couleur des cheveux
Fonctions humaines
  • Dormir
  • Se réveiller
  • Manger
  • Conduire un moyen de transport

Avant de continuer plus loin, nous devons faire un peu de philosophie. La structure précédente n’est pas un être humain en soi; elle ne décrit que l’idée ou le concept derrière un être humain. Elle décrit ce que c’est d’être humain. Être un humain c’est avoir une taille, des cheveux, dormir, etc. C’est très important pour la programmation d’objets. Ce patron d’être humain est appelé un classe. Une classe est différente d’un objet. Vous êtes un objet. Je suis un objet. La personne dans la rue est un objet. Albert Einstein est un objet. Nous sommes tous des personnes, des instances du monde réel  de ce qu’est un être humain.

La classe est ce qui sert de modèle pour les objets.

Utiliser un objet

Avant que l’on embarque sur la programmation d’une classe même, commençons par regarder comment l’utilisation d’objets dans notre programme principale (i.e. setup() et draw()) rend le monde meilleur.

Considérons le pseudo-code pour un simple projet qui déplace un rectangle horizontalement sur la largeur de la fenêtre ( Imaginons que le rectangle est une voiture).

Données (Variables globales)
  • Couleur de la voiture
  • Position x de la voiture
  • Position y de la voiture
  • Vitesse de la voiture
Configuration (setup())
  • Initialiser la couleur de la voiture
  • Initialiser la position de départ de la voiture
  • Initialiser la vitesse de la voiture
Rendu (draw())
  • Remplir l’arrière-plan
  • Afficher la voiture en couleur et à la position donnée
  • Incrémenter la position de la voiture par la vitesse
Pour implémenter le pseudo-code précédent, nous définirions les variables globales dans le haut du programme, initialiserons celles-ci dans setup(), et appelerons les fonctions pour déplacer et dessiner la voiture dans draw(). Donc cela donnerait quelques choses qui ressemble à ceci :
color c = color(0);
float x = 0;
float y = 100;
float vitesse = 1;

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

void draw() {
  background(255);
  move();
  display();
}

void move() {
  x = x + vitesse;
  if (x > width) {
    x = 0;
  }
}

void display() {
  fill(c);
  rect(x,y,30,10);
}
La programmation orientée objet permet de prendre toutes le variables et les fonctions du programme principale et de les mettre dans un objet voiture. Un objet voiture aura connaissance de ses données soit la couleur, la position et la vitesse. L’objet connaîtra aussi les actions qu’il pourra effectuer, les méthodes (fonctions à l’intérieur d’un objet), la voiture peut conduire et s’afficher. En utilisant un design orienté objet, le pseudo-code s’améliore et ressemblera à ceci : Données (Variables globales)
  • Objet voiture
Configuration (setup())
  • Initialiser l’objet voiture
Rendu (draw())
  • Remplir l’arrière-plan
  • Conduire l’objet voiture
  • Afficher la voiture
Remarquez que l’on a retiré toutes les variables globales de la première exemple. Au lieu d’avoir des variables séparées pour la couleur, la position et la vitesse, on a maintenant une seule variable soit la variable voiture! Et au lieu d’initialiser toutes les variables, on initialise qu’une seule chose, la variable voiture. Où sont passées toutes les variables? Elles existent encore, dorénavant elles sont à l’intérieur de l’objet voiture (et sont définies dans la classe Voiture que l’on verra prochainement). Si l’on passe au vrai code, on devrait avoir quelques choses qui ressemble à ceci :
Voiture maVoiture;

void setup()  {    
  maVoiture = new Voiture();   
}    

void draw()  {    
  background(255);   
  maVoiture.conduire();   
  maVoiture.afficher();   
}
On regardera en détail le code précédent, mais avant nous allons regarder comment la classe Voiture elle-même est écrite.

Écrire la classe

L’exemple précédent de la voiture démontre comment l’utilisation  d’objet en programmation permet de créer du code propre et lisible. La partie la plus longue est d’écrire le patron de la classe, c’est-à-dire la classe elle-même. Lorsque l’on apprend la POO pour la première fois, une des méthode d’apprendre le fonctionnement est de comparer du code avec et sans objets. Toutes les classes doivent inclure quatre éléments soit le nom, les données, le constructeur et les méthodes (Techniquement, on pourrait créer une classe qu’avec le nom, mais l’objectif de faire de la POO est d’inclure tous ces éléments). Voici une comparaison entre du code non orienté objet et du code orienté objet.
// Non orienté objet Orienté objet
color c;
float xPos;
float yPos;
float xVitesse;

void setup() {
  size (400, 400);
  c = color (255);
  xPos = width / 2;
  yPos = height / 2;
  xVitesse = 1;
}

void draw() {
  background(0);
  conduire();
  afficher();
}

void conduire() {
  xPos = xPos + xVitesse;
  if (xPos > width) {
    xPos = 0;
  }
}

void afficher() {
  rectMode(CENTER);
  fill (c);
  rect (xPos, yPos, 20, 10);
}
class Voiture {
  color c;
  float xPos;
  float yPos;
  float xVitesse;
  
  Voiture () {
    c = color (255);
    xPos = width / 2;
    yPos = width / 2;
    xVitesse = 1;
  }
  
  
  
  
  
  
  
  
void conduire () {
    xPos = xPos + xVitesse;
    if (xPos < width) {
      xPos = 0;
    }
  }
  
  void afficher () {
    rectMode(CENTER);
    fill (c);
    rect (xPos, yPos, 20, 10);
  }

}
Nom de la classe : Le nom de la classe est spécifié par « class PeuImporteLeNomQueVousChoisissez ». Après le nom de la classe, on enferme tout le code pour la classe entre les accolades. Traditionnellement, les noms de classe débutent avec une majuscule pour les distinguer des noms de variables qui sont traditionnellement en minuscule. Données : Les données pour une classe sont une collection de variables. Ces variables sont souvent référées comme des variables d’instance puisque chaque instance d’un objet contient la collection de variables. Constructeur : Le constructeur est une fonction spéciale à l’intérieur de la classe qui crée l’instance de l’objet même. C’est l’endroit où l’on donne les instruction sur la manière de procéder pour configurer un objet. C’est comme la méthode setup() dans Processing à la différence que le constructeur est utilisé pour créer un objet individuel à l’intérieur d’un projet. Le constructeur a toujours le même nom que la classe et est appelé en utilisant le mot clé new : « Voiture maVoiture = new Voiture(); » Fonctionnalités : On peut ajouter des fonctionnalités à notre objet en écrivant des méthodes. Pour ajouter une classe dans Processing, il suffit d’ajouter le code de celle-ci à l’extérieur des blocs setup() et draw().
void setup() {

}

void draw() {

}

class Voiture() {

}
Une autre façon de créer une nouvelle classe dans Processing est de cliquer sur la petite flèche à droite des onglets afficher, de sélectionner « Nouvel onglet »  et de donner un nouveau nom qui débute avec une majuscule. 2015-11-10_14-14-30 Nouveau_Nom_2015-11-10_14-16-19 La syntaxe générale pour créer une classe est la suivante :
class ClasseNom {
  // Mes variables
  
  // Constructeur
  ClasseNom () {
    // Code pour initialiser
    // les variables
    
  }
  
  // Autres fonctionnalités
  
}

Utiliser un objet : Les détails

Précédemment, nous avons rapidement survolé comment les objets peuvent simplifier la programmation.
// Étape 1 : Déclarer les objets
Voiture maVoiture;

void setup()  {    
  // Étape 2, Initialiser les objets.
  maVoiture = new Voiture();   
}    

void draw()  {    
  background(255);  
  // Étape 3. Appeler les méthodes de l'objets. 
  maVoiture.conduire();   
  maVoiture.afficher();   
}
Regardons de plus près le fonctionnement des trois étapes sur la méthode d’utilisation d’un objet dans votre projet.

Étape 1. Déclarer la variable d’un objet

Une variable est toujours déclarée en spécifiant le type et le nom. Avec les types de base tel qu’un entier, cela ressemble à ceci :
// Déclaration de variable    
int var;  // type Nom
Les types de données primitifs sont des informations singulières : un entier, un nombre à virgule, un caractère, etc. Déclarer une variable qui contient un objet est assez similaire. La différence est que le type est le nom de la classe, quelque chose que l’on a fabriqué, dans ce cas-ci « Voiture ». Les objets ne sont pas des types primitifs et sont considérés comment des types de données complexes.

Étape 2. Initialiser les objets

Pour initialiser les objets, il faudra faire appel au constructeur de la classe. Une variable primitive peut s’initialiser avec l’opérateur « = ». Par exemple :
x = 10;
Dans le cas d’un objet, c’est un peu plus complexe. Au lieu de simplement assigner une valeur comme un entier ou un caractère, on doit construire l’objet. Un objet est construit avec l’opérateur « new« . Par exemple
// Initialisation d'un objet
maVoiture = new Voiture();
Dans l’exemple précédent, « maVoiture » est le nom de variable de l’objet et le « = » indique que l’on lui assigne quelque chose. Ce quelque chose est une nouvelle instance d’un objet « Voiture ». Ce que l’on fait réellement, c’est que l’on initialise un objet Voiture. Quand on initialise une variable primitive tel un entier, on ne fait que lui faire prendre la valeur d’un nombre. Mais un objet peut contenir plusieurs pièces de données. Si l’on revient à la classe Voiture, cette ligne appelle la méthode constructeur, une méthode nommée « Voiture() » qui initialise toutes les variables de l’objet et s’assure que l’objet Voiture est prête à l’utilisation. Une chose; avec les primitives numériques, si on oublie d’initialiser la variable (ex : lui donner une valeur de 10), Processing lui donnera une valeur par défaut de zéro. Un objet (ex : « maVoiture »), toutefois, n’a pas de valeur par défaut. Si on oublie d’initialiser un objet, Processing lui assignera la valeur nullnull signifie rien. Pas zéro… juste rien. Le vide. Si vous vous trouvez face à une erreur qui dit « NullPointerException » (c’est relativement fréquent), cette erreur est souvent due au fait que vous avez oublié d’initialiser un objet.

Étape 3. Utiliser un objet

Une fois que l’on a réussi à déclarer et initialiser un objet, on peut l’utiliser. Utiliser un objet implique que l’on peut utiliser les fonctionnalités qui sont programmées dans l’objet. Un objet humain peut manger, une voiture peut conduire, un chien peut japper, etc. Appeler une fonction à l’intérieur d’un objet est réalisé avec une syntaxe à point : nomVariable.fonctionDeLObjet (Paramètres); Dans le cas de la classe Voiture, aucune des fonctions disponibles ne possède de paramètre. Alors on les utilises comme suit :
// Les fonctions sont appelées avec la "syntaxe à point".
maVoiture.conduire();
maVoiture.afficher();
// À continuer

Exercices

  1. Réaliser un programme qui a les classes suivantes
    1. Voiture
    2. Chien
    3. Oiseau
    4. Joueur
    5. Balle
    6. Zombie
    7. Rectangle
    8. Polygone
  2. Dans chacun des objets précédents, il devra y avoir
    • Une méthode pour déplacer et afficher les objets.
    • Une méthode pour afficher faire le son de l’objet s’il y en a un. Le son est un message qui s’affichera dans la console à l’aide de la méthode « println ». Par exemple, le chien aura la méthode « japper() » qui affichera « Wouf wouf! » dans la console.
    • Les méthodes représentant les différentes actions que chaque classe peut faire.
    • Vous pouvez utiliser des formes primitives pour afficher les objets. Par exemple un rectangle pour afficher une voiture.
  3. Dans votre programme, utilisez les fonctionnalités des objets que vous avez créé.
 

par

Étiquettes :

Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.