Blog ENI : Toute la veille numérique !
-25€ dès 75€ sur les livres en ligne, vidéos... avec le code FUSEE25. J'en profite !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Algorithmique
  3. La programmation orientée objet
Extrait - Algorithmique Des bases à la programmation orientée objet en Java (avec exercices et corrigés) (2e édition)
Extraits du livre
Algorithmique Des bases à la programmation orientée objet en Java (avec exercices et corrigés) (2e édition) Revenir à la page d'achat du livre

La programmation orientée objet

Présentation

1. Qu’est-ce que la programmation orientée objet ?

La programmation orientée objet, souvent abrégée en POO, est un autre paradigme de programmation, qui vient s’ajouter aux paradigmes de programmation impérative et procédurale utilisés précédemment.

Pour introduire ce paradigme de programmation, je prends tout d’abord un exemple, avant de vous donner une définition formelle de ce qu’est la programmation orientée objet. Supposons que nous souhaitions coder un jeu de bataille navale (une vraie, avec deux joueurs s’affrontant et cherchant à couler les bateaux de différents types de l’adversaire). Il serait nécessaire, sans la POO, de définir des variables pour connaître, pour chaque bateau, son type, sa longueur et ses coordonnées. Il serait également nécessaire de faire des procédures et des fonctions permettant de choisir sa position, de tester si un tir touche le bateau… Toutes ces variables, ces fonctions et ces procédures sont des éléments qui, d’un point de vue de l’algorithme, sont indépendants les uns des autres et pourtant, d’un point de vue de la logique, elles forment un tout, elles vont bien ensemble. Le principe de la programmation orientée objet consiste donc à regrouper ces éléments au sein d’un...

Les notions de classe et d’instance

En programmation orientée objet, nous définissons donc des classes représentant les objets que nous souhaitons modéliser. Chaque classe définit un concept : il est possible d’en donner une définition. Par exemple, un bateau de bataille navale est défini par son type, sa longueur et ses coordonnées, mais également par le fait de pouvoir être touché par un tir de l’adversaire, voire coulé. Tous les bateaux de ce jeu respectent cette définition de la classe Bateau. Il y a un ensemble de bateaux intervenant dans une partie de bataille navale. Ces différents bateaux correspondent aux instances de la classe Bateau. Une instance d’une classe est donc un élément respectant la définition de cette classe. Dans notre jeu de bataille navale, il sera ainsi nécessaire de créer une classe Bateau et, à partir de cette classe, de créer dix instances pour représenter les bateaux des deux joueurs.

Pour prendre une image pour illustrer la différence entre ces deux concepts : une classe peut être vue comme un moule et les instances comme les pâtés de sable qui ont été construits à partir de celui-ci. Toutes les instances ont bien une définition commune : elles ont la même forme que le moule, mais ceux-ci...

La déclaration d’une classe

En algorithmique, les classes se déclarent au même niveau que les algorithmes, les sous-algorithmes et les constantes globales.

Syntaxe :

Classe NomDeLaClasse  
  
FClasse 

Leur déclaration commence par le mot-clé Classe et se termine par le mot-clé FClasse (Fin de la classe). Le nom d’une classe commence obligatoirement par une majuscule.

En Java, il faut savoir que tout est objet. Donc, sans le savoir, nous déclarions déjà des classes. Les fameuses lignes que nous écrivions systématiquement définissaient la classe dans laquelle nous écrivions nos procédures, nos fonctions…

Syntaxe :

public class NomDeLaClasse { 
 
} 

Une classe Java doit être définie dans un fichier portant le même nom avec l’extension .java.

Il est conseillé de définir une classe au sein d’un package. Un package n’est rien d’autre qu’un groupement de classes. Ainsi, toutes les classes portant sur un même sujet sont regroupées au sein d’un même package.

Le nom du package doit être différent des noms des autres packages pour éviter un conflit. Pour ce faire, il est conseillé d’utiliser le nom de domaine de sa société et de le transformer de la manière suivante :

extension.nomDeDomaine.nomDuPackage...

Les attributs d’instance

Les attributs d’instance sont les valeurs caractérisant une instance. La couleur du pion et le fait qu’il a été transformé en dame par exemple. Ces attributs correspondent aux fameuses variables qui vont bien ensemble.

Au sein de la classe, ces attributs sont définis de manière similaire à la définition d’une variable. La seule différence est que le mot-clé Variable est remplacé par le mot-clé Attribut.

Syntaxe :

Attribut nomDeLAttribut : type 

Exemple :

Classe Bateau   
Attribut type : texte  
Attribut longueur : entier  
Attribut latitude : entier  
Attribut longitude : entier  
Attribut horizontal : booléen  
Attribut partiesTouchees : entier <- 0  
  
FClasse 

Notre classe Bateau définit donc six attributs d’instance : type de type texte (porte-avions, croiseur, contre-torpilleur, sous-marin ou torpilleur), longueur de type entier (longueur en nombre de cases utilisées par le bateau), latitude et longitude de type entier (les coordonnées de la première case utilisée par le bateau), horizontal de type booléen (vrai si le bateau est positionné horizontalement et faux s’il est vertical) et partiesTouchees de type entier (nombre de tirs ayant touché ce bateau). Vous remarquerez que, de manière similaire aux variables...

Les constantes

Il est également possible de déclarer une constante au sein d’une classe en la déclarant dans la section de déclaration avec les attributs, avec la même syntaxe que précédemment.

Exemple :

Classe Bateau  
Attribut type : texte  
Attribut longueur : entier  
Attribut latitude : entier  
Attribut longitude : entier  
Attribut horizontal : booléen  
Attribut partiesTouchees : entier <- 0  
 
Constante TOUCHE : entier <- 1  
Constante COULE : entier <- 2  
  
FClasse 

Pour pouvoir accéder à la valeur de la constante, il est nécessaire de faire précéder son nom du nom de la classe dans laquelle elle a été définie.

Syntaxe :

NomDeLaClasse.NOM_DE_LA_CONSTANTE 

Exemple :

Bateau.COULE 

En Java, nous avons déjà défini des constantes au sein d’une classe, il s’agit de nos constantes globales.

Syntaxe :

visibilité static final type NOM_DE_LA_CONSTANTE_GLOBALE = valeur; 

Les visibilités disponibles pour les constantes sont les mêmes que celles présentées au paragraphe précédent pour les attributs. Comme la valeur n’est pas modifiable, toutes les visibilités sont envisageables sans enfreindre le principe d’encapsulation.

Pour faire appel à une constante, il faut la faire...

Les méthodes d’instance

Les méthodes d’instance sont les actions réalisables sur les instances. Elles correspondent aux procédures et fonctions qui manipulent les variables allant bien ensemble citées en introduction de ce chapitre.

Une méthode est donc une fonction ou une procédure qui est incluse dans une classe.

1. La déclaration d’une méthode d’instance

Ces méthodes sont déclarées après le mot-clé Méthodes :

Classe NomDeLaClasse  
# déclaration des attributs  
  
Méthodes  
# déclaration des méthodes  
  
FClasse 

Les méthodes d’instance peuvent accéder aux attributs d’instance en préfixant leur nom par instance. Ce mot-clé instance permet d’accéder à l’instance courante, c’est-à-dire l’instance sur laquelle cette méthode est appelée.

Voici cela illustré avec notre classe Bateau :

Classe Bateau  
Attribut type : texte  
Attribut longueur : entier  
Attribut latitude : entier  
Attribut longitude : entier  
Attribut horizontal : booléen  
Attribut partiesTouchees : entier <- 0  
  
Constante TOUCHE : entier <- 1  
Constante COULE : entier <- 2  
  
 Méthodes  
  
Procédure initialiser(type : texte, longueur : entier)  
Début  
 instance.type <- type  
 instance.longueur <- longueur  
Fin  
 ...

La création d’une instance

1. La déclaration et l’instanciation d’une variable de type classe

Nous savons maintenant créer des classes, il est grand temps d’apprendre à y faire appel ! Ce paragraphe a donc pour objectif d’expliquer comment créer une instance et comment faire appel à ses méthodes.

L’écriture d’une classe correspond à la création d’un nouveau type. Il est donc possible de déclarer des variables de ce type.

Syntaxe :

Variable nomInstance : NomDeLaClasse 

Exemple :

Variable croiseur : Bateau 

Tout comme pour les tableaux dont la taille n’a pas été indiquée entre les crochets, cette déclaration n’a créé qu’une variable capable de contenir une instance de Bateau. Pour stocker cette instance de Bateau dans cette variable, il faut la créer. Cette opération s’appelle l’instanciation.

Syntaxe :

nom_instance <- nouveau NomDeLaClasse() 

Exemple :

croiseur <- nouveau Bateau() 

Il est également possible de créer simultanément l’instance et la variable permettant de la stocker en écrivant :

Variable nomDeLInstance : NomDeLaClasse <- nouveau NomDeLaClasse() 

Une fois l’instance créée, il est possible de faire appel à ses méthodes d’instance en utilisant la syntaxe suivante :

nomDeLInstance.nomDeLaMethodeDInstance(paramètres) 

Voici un exemple d’algorithme utilisant la classe Bateau :

Algo TestBateau  
Variable croiseur : Bateau <- nouveau Bateau()  
Variable resultatTir : entier  
Début  
 croiseur.initialiser("Croiseur", 4)  
 # positionnement dans le sens vertical avec pour première case  
 #(3; 7)  
 croiseur.positionner(3, 7, FAUX 
  
 # tir en (2;4) : normalement, le bateau n'est pas touché  
 resultatTir <- croiseur.testerTir(2, 4)  
 Si resultatTir = 0 Alors  
   écrire("Un tir hors du bateau ne lui a pas causé de dégâts ! " &  
Tout va bien !")  
 Sinon  
   écrire("Il y a un problème ! Un tir hors du bateau...

Les constructeurs

Lors de la création d’une instance (exemple : croiseur <- nouveau Bateau()), différentes opérations sont réalisées. Tout d’abord, il est nécessaire de réserver l’espace mémoire nécessaire pour stocker les informations de l’instance (cet aspect-là est expliqué dans le chapitre La mémoire). Ensuite, les attributs d’instances sont initialisés grâce au constructeur. Enfin, la variable devant contenir l’instance est valorisée.

1. Le constructeur par défaut

En algorithmique comme en Java, dans une classe, en l’absence de la déclaration d’au moins un constructeur, il existe un constructeur par défaut. Ce constructeur est alors implicitement ajouté à la classe. Le constructeur par défaut ne prend pas d’argument. Il fait appel au constructeur sans argument de la classe parent (cela est abordé dans la section L’héritage du chapitre prochain) et initialise les attributs à leurs valeurs par défaut (faux pour des booléens, zéro pour des nombres, le caractère nul pour les caractères et l’absence de valeur (null) pour les instances et les tableaux).

Dans l’exemple de la bataille navale, aucun constructeur n’a été explicitement déclaré. Un constructeur par défaut y a donc implicitement été ajouté et c’est celui-ci qui était appelé lors de la création de l’instance.

2. Les constructeurs

Il est possible de déclarer un ou des constructeurs afin d’initialiser les attributs d’instance avec des valeurs plus adaptées ou des valeurs choisies. Pour définir un constructeur, il faut utiliser la syntaxe suivante au sein de la section Méthodes de la classe :

Constructeur(listeDesParamètres)  
Début 
 #Instructions  
  
Fin 

Par exemple, il est possible de définir un constructeur pour la classe Bateau :

Classe Bateau  
Attribut type : texte  
Attribut longueur : entier  
Attribut latitude : entier  
Attribut longitude : entier  
Attribut horizontal : booléen  
Attribut partiesTouchees : entier <- 0  
  ...

Les attributs de classe

Il existe deux catégories d’attributs :

  • Les attributs d’instance

  • Les attributs de classe

La première catégorie, les attributs d’instance présentés à la section du même nom dans ce chapitre, représente des éléments qui sont propres à chaque instance. Dans l’exemple de la bataille navale, chaque instance de bateau possède son propre type, sa propre longueur, son propre positionnement (latitude, longitude et orientation verticale ou horizontale) et son propre compteur de tirs l’ayant endommagé. Pour tous ces attributs d’instance, une modification de valeur n’affecte qu’une seule instance. Par exemple, si un tir atteint l’un des bateaux d’un joueur, seule la valeur de l’attribut partiesTouchees de ce bateau est modifiée. Les valeurs de cet attribut pour toutes les autres instances restent inchangées.

La seconde catégorie, les attributs de classe, représente les éléments qui sont communs ou collectifs à la classe.

Les éléments communs correspondent à une valeur qui serait la même pour l’ensemble des instances de cette classe. Le caractère pour afficher une partie de bateau indemne et celui pour afficher une partie de bateau atteinte par un tir sont des éléments communs à toutes les instances....

Les méthodes de classe

Les méthodes de classe, à l’instar des attributs de classe, sont des méthodes dont l’exécution ne dépend pas d’une instance particulière. Ces méthodes travaillent donc sur la classe et non sur les instances de celles-ci.

Par exemple, une méthode de classe pourrait afficher les règles de positionnement d’un bateau sur la grille de la bataille navale. Cette méthode ne dépend pas d’un bateau plutôt que d’un autre, c’est donc une méthode de classe. Les méthodes de classe peuvent accéder aux attributs de classe, par contre elles ne peuvent pas accéder aux attributs d’instance puisque ces attributs dépendent d’une instance.

1. La déclaration d’une méthode de classe

Les méthodes de classe sont définies au sein d’une section MethodesDeClasse

Syntaxe :

Classe NomDeLaClasse  
# déclaration des attributs  
  
Méthodes  
# déclaration des méthodes d'instance  
  
MéthodesDeClasse  
# déclaration des méthodes de classe  
  
FClasse 

Exemple :

Classe Bateau  
Attribut type : texte  
Attribut longueur : entier  
Attribut latitude : entier  
Attribut longitude : entier  
Attribut horizontal : booléen  
Attribut partiesTouchees : entier <- 0  
  
AttributDeClasse symboleTouche : caractère <- 'x'  
  
Constante TOUCHE : entier <- 1  
Constante COULE : entier <- 2  
  
Méthodes  
  
Constructeur(type : texte, longueur : entier)  
Début  
 instance.type <- type  
 instance.longueur <- longueur  
Fin  
  
Constructeur(type : texte, longueur : entier, latitude : entier,  
longitude : entier, horizontal : booléen) AutreConstructeur(type,  
longueur)  
Début  
 positionner(latitude, longitude, horizontal)  
Fin  
  
Fonction getType() Retourne texte  
Début  
 Retourner...

Les instances : un type référence

Les instances contiennent un ensemble de valeurs, tout comme les tableaux. Pour les mêmes raisons d’optimisation de l’utilisation des zones mémoire, les instances sont des types référence. L’utilisation de la mémoire et la manière d’y stocker une instance est présentée plus en détail dans le chapitre La mémoire. Pour l’instant, il faut être conscient que lorsqu’une instance est passée en paramètre, est retournée par une méthode ou une fonction ou bien est affectée à une autre variable, aucune copie d’instance n’a été réalisée.

Ce qui est recopié, c’est la référence vers cette instance.

Par exemple, supposons qu’une instance de bateau est passée en paramètre. Si une modification est effectuée au sein de la méthode, la modification est effective dans l’instance même après la fin de l’appel de la méthode. Car dans cet exemple, il n’y a qu’une seule instance de bateau et plusieurs références permettant d’accéder à celle-ci.

Exercices

1. Les dés

Créer une classe modélisant un dé à jouer. Cette classe possède :

  • deux attributs d’instance : l’un permettant de connaître le nombre de faces que possède le dé et l’autre pour stocker la dernière face qui a été tirée ;

  • deux constructeurs : l’un prenant en paramètre le nombre de faces pour le dé à créer et l’autre, sans paramètre, créant un dé classique à six faces ;

  • des méthodes getter pour les deux attributs ;

  • une méthode setter uniquement pour changer le nombre de faces ;

  • une méthode d’instance permettant de simuler le lancer de dé, retournant la valeur tirée aléatoirement par le dé.

Écrire un algorithme principal utilisant cette classe pour créer trois dés : l’un à six faces, un autre à dix faces et le dernier à douze faces. Les trois dés sont lancés jusqu’à ce que la somme des dés soit supérieure ou égale à vingt.

2. Les clients

Pour les besoins d’un site de vente en ligne de livres d’informatique, les éditions ENI par exemple, il vous est demandé de créer une classe permettant de modéliser un client. Les clients ont tous un nom et vous devez leur attribuer un numéro de client. Écrivez également un algorithme de test permettant de saisir et d’afficher les clients.

Exemple d’exécution possible :

-- Menu --

1 - Afficher les clients

2 - Créer un client

3 - Quitter

2

Nom ?

Francine SCHNEIDER

Client n°1 [Francine SCHNEIDER] ajouté...

Solutions des exercices

1. Les dés

Classe De  
Attribut nbFaces : entier  
Attribut faceTiree : entier  
  
Méthodes  
  
Constructeur(nbFaces : entier)  
Début  
 instance.nbFaces <- nbFaces  
 instance.faceTiree <- lancer()  
Fin  
  
Constructeur() AutreConstructeur(6)  
Début  
Fin  
  
Fonction getNbFaces() Retourne entier  
Début  
 Retourner instance.nbFaces  
Fin  
  
Fonction getFaceTiree() Retourne entier  
Début  
 Retourner instance.faceTiree  
Fin  
  
Procédure setNbFaces(nbFaces : entier)  
Début  
 instance.nbFaces <- nbFaces  
Fin  
  
Fonction lancer() Retourne entier  
Début  
 instance.faceTiree <- aléa(1, instance.nbFaces)  
 Retourner instance.faceTiree  
Fin  
  
FClasse 

Algo TestDes  
Constante SEUIL : entier <- 20  
Variable de6, de10, de12 : De  
Début  
 de6 <- nouveau De()  
 de10 <- nouveau De(10)  
 de12 <- nouveau De(12)  
 Répéter  
   écrire("tentative d'arriver à " & SEUIL)  
   écrire("Lancement du dé à six faces : " & de6.lancer())  
   écrire("Lancement du dé à dix faces : " & de10.lancer())  
   écrire("Lancement du dé à douze faces : " & de12.lancer())  
 TantQue de6.getFaceTiree() + de10.getFaceTiree() +  
 de12.getFaceTiree() < SEUIL FRépéter  
 écrire("Victoire !")  
Fin 

2. Les clients

Classe Client  
Attribut nom : texte  
Attribut numCli : entier  
AttributDeClasse nbClients : entier <- 0  
Méthodes  
  
Constructeur(nom : texte)  
Début  
 instance.nom <- nom  
 Client.nbClients <- Client.nbClients...