Programmation orientée objet en JAVA

Introduction

Ce chapitre a pour but de montrer comment certains concepts de la programmation orientée objet sont implémentés en Java, à commencer, bien entendu par les notions fondamentales d'objet et de classe.

En préliminaire, notons bien que contrairement au C++, Java n'autorise ni les fonctions globales ni les variables globales ce qui a pour effet d'imposer l'encapsulation de toute déclaration de variables ou de tout code à l'intérieur de classes. Ceci fait de Java un langage à objets par opposition au C++ qui reste un langage orienté objets.

Les classes

Généralités

Rappelons qu'un objet est une entité cohérente qui regroupe des données sous la forme d'attributs et le code qui l'exploite sous forme de méthodes.

Une classe est la description d'un ensemble d'objets de structure identique. Elle définit l'ensemble des attributs qui composent un objet et fournit le code des méthodes.

Consultez le poly "L'objet pour les débutants" pour de plus amples informations.

Classes publiques, notion de package, notion de CLASSPATH

En Java, les classes sont organisées en package qui forment une arborescence. Cette notion est orthogonale à celle d'héritage. Un package est un ensemble de classes attachées à un même concept. Le meilleur exemple est assurément donné par l'API Java fournie en standard avec le compilateur. On trouve les packages suivants :

Par exemple, dans le package java.io on trouve toutes les classes associées aux entrées sorties alors que java.net contient les classes spécialisées dans la programmation des réseaux.

Les packages peuvent à leur tour se ramifier en sous packages. Par exemple, le package java.rmi possède plusieurs sous packages dont java.rmi.server et java.rmi.activation. L'idée consiste à faire descendre tous vos packages d'une même racine qui permette de vous identifier rapidement comme le concepteur des classes. Le nom de ce package de haut niveau peut être, par exemple, l'acronyme de votre société. Par exemple, la plupart des classes que vous rencontrerez au cours de ce tutorial vont appartenir à un sous package de obc (Ours Blanc des Carpathes Software, la société fictive de l'auteur).

Il est important de noter que l'organisation sur disque de vos fichiers doit refléter celle des packages. En effet, chaque package ou sous package est associé à un répertoire du disque. L'imbrication des package étant directement traduite par celle des répertoires. Par exemple, une classe appartenant au package obc.rmi.banque se trouvera dans un sous répertoire obc/rmi/banque. Notez que nous avons pris soin de ne pas donner de référence absolue de ce répertoire. En effet, l'emplacement de la racine peut se trouver n'importe ou sur votre disque pour peu que sa racine soit spécifiée dans une variable d'environnement nommée CLASSPATH.

En fait, il est même possible de spécifier plusieurs racines différentes à condition qu'elles soient toutes présentes dans le CLASSPATH. Pour bien comprendre son utilité, il nous faut étudier le modèle d'exécution du Java.

De même que le nom du package correspond au chemin menant au fichier, le nom du fichier source Java est représentatif de la classe qu'il contient. Par exemple, si vous voulez créer une classe Journal dans le package obc.audit le fichier doit s'appeller Journal.java et doit être situé dans le sous répertoire obc/audit soit au final obc/audit/Journal.java. (consultez le guide de style pour les conventions de nommage des classes ou packages).

Si le fichier doit porter le même nom que la classe, est ce que cela signifie qu'un même fichier de source (d'extension .java) ne peut contenir qu'une seule classe ? pas tout à fait. Il ne peut contenir qu'une seule classe publique, c'est à dire une seule classe de visibilité universelle (public ou universal scope en Anglais).

On dit qu'une classe est publique si elle est visible, c'est à dire référençable par une autre classe n'appartenant ni au même fichier source ni au même package. Un même fichier source peut donc contenir autant de classes non publiques que vous le souhaitez, mais une seule classe publique. Selon le modificateur de visibilité que vous utilisere, les classes non publiques pourront être accessibles aux  classes appartenant au même package ou uniquement aux classes contenues dans le même fichier source.

L'intérêt d'une telle manoeuvre tient essentiellement à la dissimulation d'implémentation. En effet, supposons que vous désiriez coder une classe ArbreBinaire. Dans un premier temps, vous l'implémentez à l'aide de cellules liées entre elles. Le programmeur client d'une telle classe n'a pas (et ne veut probablement pas) à savoir qu'il existe une classe cellule. En outre, s'il peut accéder à cette dernière, il pourrait avoir l'idée de l'utiliser ce qui pourrait s'avérer désastreux si vous décidiez de changer le mode d'implémentation par un tableau. Cette classe doit donc être cachée : il suffit pour cela de ne pas la rendre publique.

Mieux encore, vous pourriez l'encapsuler à l'intérieur de la classe ArbreBinaire. Ainsi, elle ne serait utilisable que de l'intérieur de la classe ArbreBinaire ce qui est bien le résultat recherché. Le langage Java autorise l'imbrication et même la création de classes anonymes comme nous le verrons plus tard.

Récapitulatif :

L'implémentation des classes

Compiler du code source java

Rappelons immédiatement que la compilation d'un fichier source .java ne fournit pas du code objet natif mais un format intermédiaire connu sous le nom de byte code. C'est ce format standard qui sera ensuite interprété vers des instructions natives sur la machine d'exécution par la machine virtuelle java.

Si vous optez pour l'environnement de développement minimaliste fourni par Sun et nommé JDK (Java Development toolkit) le compilateur porte le nom de javac (java compiler). Pour compiler un fichier .java, il suffit de tapper :

javac {chemin_complet}fichier.java

Bien entendu, il est possible de fournir des options au compilateur. Toutefois, du fait des spécificités du langage et en particulier le fait de passer par un byte code et l'absence de préprocesseur font qu'il y a très peu d'options de compilation. Les plus importantes sont les suivantes :

-deprecation Affiche des messages d'avertissement si vous utilisez des méthodes ou des classes dont l'usage n'est plus recommandé du fait des l'avancée du langage
-classpath=LISTE_DE_CHEMINS Permet de spécifier la liste des chemins de recherche des classes
-d=CHEMIN Emplacement des fichiers .class en sortie de compilation

L'intérêt de l'option -d est de séparer les fichiers source (.java) des fichiers de compilation en bytecode (.class), ce qui a plusieurs effets positifs :

D'une part, vos répertoires sont plus propres car ils ne contiennent qu'un seul type de fichiers.

La séparation du code source permet d'utiliser plus facilement les utilitaires de contrôle de version (CVS, par exemple)

D'autre part, lors du déploiement de vos classes, vous ne voudrez probablement pas fournir le code source et il vous sera plus facile d'empackager vos fichiers .class s'ils se trouvent dans des répertoire séparés.

L'option -classpath vous permet de spécifier la liste des chemins de recherche des fichiers .class Si vous spécifiez -classpath sur la ligne de commande, la variable CLASSPATH ne sera pas prise en compte.