Nothing Special   »   [go: up one dir, main page]

Chap III - Les Concepts de Base de La POO

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 7

PROGRAMMATION JAVA – LICENCE 2

Chapitre III : Les concepts de bases de la POO


I. Vue d’ensemble de la POO
1. L’objet
Il est impossible de parler de Programmation Orientée Objet sans parler d'objet, bien entendu. Tâchons
donc de donner une définition aussi complète que possible d'un objet.

Un objet est avant tout une structure de données. Autrement, il s'agit d'une entité chargée de gérer des
données, de les classer, et de les stocker sous une certaine forme. En cela, rien ne distingue un objet d'une
quelconque autre structure de données. La principale différence vient du fait que l'objet regroupe les données et
les moyens de traitement de ces données.

Un objet rassemble de fait deux éléments de la programmation procédurale.

 Les champs : Les champs sont à l'objet ce que les variables sont à un programme : ce sont eux qui
ont en charge les données à gérer. Tout comme n'importe quelle autre variable, un champ peut
posséder un type quelconque défini au préalable : nombre, caractère... ou même un type objet.
 Les méthodes : Les méthodes sont les éléments d'un objet qui servent d'interface entre les
données et le programme. Sous ce nom obscur se cachent simplement des procédures ou fonctions
destinées à traiter les données.

Les champs et les méthodes d'un objet sont ses membres.

2. Objet et classe
Avec la notion d'objet, il convient d'amener la notion de classe. Cette notion de classe n'est apparue dans
le langage Pascal qu'avec l'avènement du langage Delphi et de sa nouvelle approche de la Programmation Orientée
Objet. Elle est totalement absente du Pascal standard.

Ce que l'on a pu nommer jusqu'à présent objet est, pour Delphi, une classe d'objet. Il s'agit donc du type à
proprement parler. L'objet en lui-même est une instance de classe, plus simplement un exemplaire d'une classe,
sa représentation en mémoire.

FABRICE PEGOFFA 25
PROGRAMMATION JAVA – LICENCE 2

Par conséquent, on déclare comme type une classe, et on déclare des variables de ce type appelées des
objets.

Si cette distinction est à bien prendre en considération lors de la programmation en Delphi, elle peut
toutefois être totalement ignorée avec la plupart des autres compilateurs Pascal. En effet, ceux-ci ne s'appuient
que sur les notions d'objet et d'instance d'objet.

3. Les trois fondamentaux de la POO


La Programmation Orientée Objet est dirigée par trois fondamentaux qu'il convient de toujours garder à
l'esprit : encapsulation, héritage et polymorphisme. Houlà ! Inutile de fuir en voyant cela, car en fait, ils ne cachent
que des choses relativement simples. Nous allons tenter de les expliquer tout de suite.

a. Encapsulation
Derrière ce terme se cache le concept même de l'objet : réunir sous la même entité les données et les
moyens de les gérer, à savoir les champs et les méthodes.

L'encapsulation introduit donc une nouvelle manière de gérer des données. Il ne s'agit plus de déclarer des
données générales puis un ensemble de procédures et fonctions destinées à les gérer de manière séparée, mais
bien de réunir le tout sous le couvert d'une seule et même entité.

Si l'encapsulation est déjà une réalité dans les langages procéduraux (comme le Pascal non objet par
exemple) au travers des unités et autres librairies, il prend une toute nouvelle dimension avec l'objet.

En effet, sous ce nouveau concept se cache également un autre élément à prendre en compte : pouvoir
masquer aux yeux d'un programmeur extérieur tous les rouages d'un objet et donc l'ensemble des procédures et
fonctions destinées à la gestion interne de l'objet, auxquelles le programmeur final n'aura pas à avoir accès.
L'encapsulation permet donc de masquer un certain nombre de champs et méthodes tout en laissant visibles
d'autres champs et méthodes.

Pour conclure, l'encapsulation permet de garder une cohérence dans la gestion de l'objet, tout en assurant
l'intégrité des données qui ne pourront être accédées qu'au travers des méthodes visibles.

b. Héritage
Si l'encapsulation pouvait se faire manuellement (grâce à la définition d'une unité par exemple), il en va
tout autrement de l'héritage. Cette notion est celle qui s'explique le mieux au travers d'un exemple. Considérons
un objet Bâtiment. Cet objet est pour le moins générique, et sa définition reste assez vague. On peut toutefois lui
associer divers champs, dont par exemple :

 Les murs ;

FABRICE PEGOFFA 26
PROGRAMMATION JAVA – LICENCE 2

 Le toit ;
 Une porte ;
 L’adresse ;
 La superficie.

On peut supposer que cet objet Bâtiment dispose d'un ensemble de méthodes destinées à sa gestion. On
pourrait ainsi définir entre autres des méthodes pour :

 Ouvrir le Bâtiment ;
 Fermer le Bâtiment ;
 Agrandir le Bâtiment.

Grâce au concept d'héritage, cet objet Bâtiment va pouvoir donner naissance à un ou des descendants. Ces
descendants vont tous bénéficier des caractéristiques propres de leur ancêtre, à savoir ses champs et méthodes.
Cependant, les descendants conservent la possibilité de posséder leurs propres champs et méthodes. Tout comme
un enfant hérite des caractéristiques de ses parents et développe les siennes, un objet peut hériter des
caractéristiques de son ancêtre, mais aussi en développer de nouvelles, ou bien encore se spécialiser.

Ainsi, si l'on poursuit notre exemple, nous allons pouvoir créer un objet Maison. Ce nouvel objet est
toujours considéré comme un Bâtiment, il possède donc toujours des murs, un toit, une porte, les
champs Adresse ou Superficie et les méthodes destinées par exemple à Ouvrir le Bâtiment.

Toutefois, si notre nouvel objet est toujours un Bâtiment, il n'en reste pas moins qu'il s'agit d'une Maison.
On peut donc lui adjoindre d'autres champs et méthodes, et par exemple :

 Nombre de fenêtres ;
 Nombre d'étages ;
 Nombre de pièces ;
 Possède ou non un jardin ;
 Possède une cave.

Notre Bâtiment a ici bien évolué. Il s'est spécialisé. Avec notre Maison, nous sommes allés plus avant dans
les détails, et elle est à même de nous offrir des services plus évolués. Nous avons complété ce qui n'était qu'un
squelette.

Ce processus d'héritage peut bien sûr être répété. Autrement dit, il est tout à fait possible de déclarer à
présent un descendant de Maison, développant sa spécialisation : un Chalet ou encore une Villa. Mais de la même
manière, il n'y a pas de restrictions théoriques concernant le nombre de descendants pour un objet. Ainsi,
pourquoi ne pas déclarer des objets Immeuble ou encore Usine dont l'ancêtre commun serait toujours Bâtiment.

On notera qu'une fois qu'un champ ou une méthode sont définis, il ou elle le reste pour tous les
descendants, quel que soit leur degré d'éloignement.

FABRICE PEGOFFA 27
PROGRAMMATION JAVA – LICENCE 2

c. Polymorphisme
Le terme polymorphisme est certainement celui que l'on appréhende le plus. Mais il ne faut pas s'arrêter
à cela. Afin de mieux le cerner, il suffit d'analyser la structure du mot : poly comme plusieurs et morphisme comme
forme. Le polymorphisme traite de la capacité de l'objet à posséder plusieurs formes.

Cette capacité dérive directement du principe d'héritage vu précédemment. En effet, comme on le sait
déjà, un objet va hériter des champs et méthodes de ses ancêtres. Mais un objet garde toujours la capacité de
pouvoir redéfinir une méthode afin de la réécrire, ou de la compléter.

On voit donc apparaître ici ce concept de polymorphisme : choisir en fonction des besoins quelle méthode
ancêtre appeler, et ce au cours même de l'exécution. Le comportement de l'objet devient donc modifiable à
volonté.

Le polymorphisme, en d'autres termes, est donc la capacité du système à choisir dynamiquement la


méthode qui correspond au type réel de l'objet en cours. Ainsi, si l'on considère un objet Véhicule et ses
descendants Bateau, Avion, Voiture possédant tous une méthode Avancer, le système appellera la fonction
Avancer spécifique suivant que le véhicule est un Bateau, un Avion ou bien une Voiture.

Le concept de polymorphisme ne doit pas être confondu avec celui d'héritage multiple. En effet, l'héritage
multiple - non supporté par le Pascal standard - permet à un objet d'hériter des membres (champs et méthodes)
de plusieurs objets à la fois, alors que le polymorphisme réside dans la capacité d'un objet à modifier son
comportement propre et celui de ses descendants au cours de l'exécution.

FABRICE PEGOFFA 28
PROGRAMMATION JAVA – LICENCE 2

II. Différentes méthodes


1. Constructeurs et destructeurs
a) Constructeurs
Comme leur nom l'indique, les constructeurs servent à construire l'objet en mémoire. Un constructeur va
donc se charger de mettre en place les données, d'associer les méthodes avec les champs et de créer le diagramme
d'héritage de l'objet, autrement dit de mettre en place toutes les liaisons entre les ancêtres et les descendants.

Il faut savoir que s'il peut exister en mémoire plusieurs instances d'un même type objet, autrement dit
plusieurs variables du même type, seule une copie des méthodes est conservée en mémoire, de sorte que chaque
instance se réfère à la même zone mémoire en ce qui concerne les méthodes. Bien entendu, les champs sont
distincts d'un objet à un autre. De fait, seules les données diffèrent d'une instance à une autre, la "machinerie"
reste la même, ce qui permet de ne pas occuper inutilement la mémoire.

Certaines remarques sont à prendre en considération concernant les constructeurs.

 Un objet peut ne pas avoir de constructeur explicite. Dans ce cas, c'est le compilateur qui se charge
de créer de manière statique les liens entre champs et méthodes.
 Un objet peut avoir plusieurs constructeurs : c'est l'utilisateur qui décidera du constructeur à
appeler. La présence de constructeurs multiples peut sembler saugrenue de prime abord, leur rôle
étant identique. Cependant, comme pour toute méthode, un constructeur peut être surchargé, et
donc effectuer diverses actions en plus de la construction même de l'objet.
 S'il n'est pas nécessaire de fournir un constructeur pour un objet statique, il devient obligatoire en
cas de gestion dynamique, car le diagramme d'héritage ne peut être construit de manière correcte
que lors de l'exécution, et non lors de la compilation.

b) Destructeurs
Le destructeur est le pendant du constructeur : il se charge de détruire l'instance de l'objet. La mémoire
allouée pour le diagramme d'héritage est libérée. Certains compilateurs peuvent également se servir des
destructeurs pour éliminer de la mémoire le code correspondant aux méthodes d'un type d'objet si plus aucune
instance de cet objet ne réside en mémoire.

Là encore, différentes remarques doivent être gardées à l'esprit.

 Tout comme pour les constructeurs, un objet peut ne pas avoir de destructeur. Une fois encore,
c'est le compilateur qui se chargera de la destruction statique de l'objet.
 Un objet peut posséder plusieurs destructeurs. Leur rôle commun reste identique, mais peut s'y
ajouter la destruction de certaines variables internes pouvant différer d'un destructeur à l'autre.
La plupart du temps, à un constructeur distinct est associé un destructeur distinct.

FABRICE PEGOFFA 29
PROGRAMMATION JAVA – LICENCE 2

 En cas d'utilisation dynamique, un destructeur s'impose pour détruire le diagramme créé par le
constructeur.

2. Pointeur interne
Très souvent, les objets sont utilisés de manière dynamique, et ne sont donc créés que lors de l'exécution.
Si les méthodes sont toujours communes aux instances d'un même type objet, il n'en est pas de même pour les
données.

Il peut donc se révéler indispensable pour un objet de pouvoir se référencer lui-même. Pour cela, toute
instance dispose d'un pointeur interne vers elle-même.

Ce pointeur peut prendre différentes appellations. En Pascal, il s'agira du pointeur Self. D'autres langages
pourront le nommer this, comme le C++...

3. Méthodes abstraites
Une méthode abstraite est une méthode qu'il est nécessaire de surcharger. Elle ne possède donc pas
d'implémentation. Ainsi, si on tente d'appeler une méthode abstraite, alors une erreur est déclenchée. Bien
entendu, il convient lors de la surcharge d'une telle méthode de ne pas faire appel à la méthode de l'ancêtre...

Les méthodes abstraites sont généralement utilisées lorsque l'on bâtit un squelette d'objet devant donner
lieu à de multiples descendants devant tous posséder un comportement analogue.

III. Visibilité
De par le principe de l'encapsulation, afin de pouvoir garantir la protection des données, il convient de
pouvoir masquer certaines données et méthodes internes les gérant, et de pouvoir laisser visibles certaines autres
devant servir à la gestion publique de l'objet. C'est le principe de la visibilité.

1. Champs et méthodes publics


Comme leur nom l'indique, les champs et méthodes dits publics sont accessibles depuis tous les
descendants et dans tous les modules : programme, unité... On peut considérer que les éléments publics n'ont
pas de restriction particulière.

Les méthodes publiques sont communément appelées accesseurs : elles permettent d'accéder aux champs
d'ordre privé.

Il existe des accesseurs en lecture, destinés à récupérer la valeur d'un champ, et des accesseurs en écriture
destinés pour leur part à la modification d'un champ. Très souvent, les accesseurs en lecture verront leur nom
commencer par get quand leurs homologues en écriture verront le leur commencer par set.

FABRICE PEGOFFA 30
PROGRAMMATION JAVA – LICENCE 2

Remarque : Les constructeurs et les destructeurs éventuels d'un objet devront bénéficier de la visibilité
publique, sans quoi un programme externe ne pourrait pas les appeler.

2. Champs et méthodes privés


La visibilité privée restreint la portée d'un champ ou d'une méthode au module où il ou elle est déclaré(e).
Ainsi, si un objet est déclaré dans une unité avec un champ privé, alors ce champ ne pourra être accédé qu'à
l'intérieur même de l'unité.

Remarque : Quand un champ est déclaré privé, même les classes descendantes n’ont pas accès direct à la
propriété privée. Ainsi, le concept d’héritage ne permet pas l’héritage des propriétés privées.

3. Champs et méthodes protégés


La visibilité protégée correspond à la visibilité privée excepté que tout champ ou méthode protégé(e) est
accessible dans tous les descendants, quel que soit le module où ils se situent.

FABRICE PEGOFFA 31

Vous aimerez peut-être aussi