• Aucun résultat trouvé

Le principe fondamental est que le langage doit permettre d'exprimer la solution d'un problème à l'aide des éléments de ce problème. Un programme traitant des images doit manipuler des structures de données représentant des images, et non leur traduction sous forme de suite de 0 et de 1. Les structures de données manipulées par un programme de gestion de person-nel doivent représenter des personnes, avec toutes les informations perti-nentes, qu'il s'agisse de texte, de date, de nombre, d'images ou autres.

Java est l'aboutissement (pour le moment, en tout cas) de ce concept. Pour Java, l'univers du problème à traiter est constitué d'objets. Cette approche est la plus naturelle, car elle correspond également à notre façon d'appré-hender notre univers. La modélisation des problèmes en est donc facilitée à l'extrême.

Tout est donc objet. Le terme d'objet est peut-être mal choisi. Il ne fait pas référence aux objets par opposition aux êtres animés. Objet signifie simple-ment "élésimple-ment de l'univers".

Les classes

Les objets appartiennent à des catégories appelées classes. L'ensemble des classes découpe l'univers. (Par univers, il faut entendre évidemment uni-vers du problème à traiter.)

Si notre problème concerne les animaux, nous pouvons créer une classe que nous appellerons animal. Si nous devons considérer les chiens, les chats et les canaris, nous créerons trois classes dérivées de la classe Animal : les classes Chien, Chat et Canari. Peu importe que cette division ne soit pas pertinente dans l'univers réel. Il suffit qu'elle le soit dans celui du problème à traiter. Nous représenterons cette division de l'univers de la façon suivante :

Animal

Chien Chat Canari

Nous pouvons, si nécessaire, créer de nouvelles classes dérivées, par exemple :

Animal

Chien Chat Canari

Teckel Labrador Caniche

Il est d'usage de représenter ainsi sous forme d'arbre inversé, la hiérarchie des classes. La classe la plus générale se trouve à la racine (en haut, puisque l'arbre est inversé). Ces deux exemples sont incomplets. En effet, toutes les classes dérivent d'une même classe, la plus générale : la classe Objet. L'ar-bre précédent doit donc être complété de la façon suivante :

Animal

Chien Chat Canari

Teckel Labrador Caniche

Objet

Pertinence du modèle

La structure que nous construisons ainsi représente l'univers du problème à traiter. S'il s'agit d'un problème de l'univers "réel", on peut être tenté d'es-sayer de construire un modèle du monde réel. C'est là un piège dans lequel il faut éviter de tomber, et ce pour deux raisons. La première est qu'un modèle du monde réel prendra en compte de très nombreux critères non pertinents en ce qui concerne notre problème. La deuxième est que ce que nous croyons être la structure du monde réel est en réalité la structure d'un modèle perceptif qui dépend de très nombreux facteurs (culturels et psy-chologiques en particulier) qui sont le plus souvent totalement parasites en ce qui concerne les problèmes que nous avons à traiter.

Par exemple, selon que nous sommes plutôt portés vers le créationnisme ou l'évolutionnisme, nous préférerons probablement l'un ou l'autre des modè-les suivants :

Objet

Humain Non humain

Animal Végétal Chose

Objet

Vivant Non vivant

Humain Animal Végétal

Peu importe lequel de ces modèles correspond le mieux au monde "réel".

La seule chose qui compte véritablement est de savoir lequel est le plus efficace pour la représentation de notre problème.

De la même façon, certaines caractéristiques des objets peuvent justifier ou non la création de classes distinctes. Ainsi, si vous écrivez un programme de gestion de personnel, vous créez probablement une classe Employé et une classe Cadre. Si vous voulez effectuer des traitements tenant compte du sexe, de l'âge et de l'adresse des membres du personnel, vous pourrez opter pour différentes structures, par exemple :

Objet

Ces deux structures peuvent sembler pertinentes, puisque si l'âge et l'adresse peuvent prendre n'importe quelles valeurs et sont susceptibles de changer (hélas), le sexe est une donnée qui détermine bien deux classes distinctes.

Cependant, dans le cadre du problème qui nous concerne, il est probable-ment beaucoup plus simple et efficace d'utiliser un modèle comme celui-ci :

Objet

Employé Cadre

sexe : âge : adresse :

sexe : âge : adresse :

Les instances de classes Considérez le modèle suivant :

Animal

Chien Chat Canari

milou rantanplan félix sylvestre titi

Il est évident que le rapport entre milou et Chien n'est pas de même nature que le rapport entre Chien et Animal. Chien est une sous-classe de Animal.

Dans la terminologie de Java, on dit que la classe Chien étend la classe Animal. En revanche, milou n'est pas une classe. C'est un représentant de la classe Chien. Selon la terminologie Java, on dit que milou est une instance de Chien.

Les membres de classes

Attention : piège ! Nous allons maintenant parler des membres d'une classe.

Contrairement à ce que l'on pourrait croire, ce terme ne désigne pas les représentants de la classe (nous venons de voir qu'il s'agissait des instan-ces), mais, en quelque sorte, ses caractéristiques. Dans l'exemple de gestion du personnel :

Objet

Employé Cadre

sexe : âge : adresse :

sexe : âge : adresse :

sexe, âge et adresse sont des membres de la classe Employé. Tous trois sont membres d'un même type : il s'agit de variables, c'est-à-dire d'éléments qui peuvent prendre une valeur. Chaque employé a un âge, un sexe et une adresse.

(Il en est de même, dans cet exemple, pour chaque cadre.)

Les employés et les cadres ne se contentent pas forcément de posséder des variables. Ils peuvent également être capables de faire quelque chose ! Pour cela, il faut qu'ils possèdent des méthodes. Les méthodes décrivent simple-ment des procédures qui peuvent être exécutées pour :

• renvoyer une valeur,

• modifier l'environnement.

Par exemple, nous pouvons définir une classe Employé possédant une va-riable matricule, et une méthode afficherMatricule().

Note : Nous respecterons ici l'usage typographique de Java :

• Les noms de classes commencent par une majuscule.

• Les noms d'instances, de variables ou de méthodes commencent par une minuscule.

• Lorsqu'un nom est composé de plusieurs mots, les mots sont accolés et chacun d’eux (sauf le premier, pour lequel les règles ci-dessus s'appli-quent) commence par une majuscule.

Les noms de méthodes sont faciles à distinguer des noms de variables car ils sont suivis de parenthèses encadrant les éventuels paramètres. Si une méthode ne prend pas de paramètres, les parenthèses sont vides mais doi-vent être présentes.

Notre nouvelle classe Employé se présente donc de la façon suivante :

03009.eps

Objet

Employé

matricule variable :

méthode :

afficherMatricule()

Il faut noter que si la méthode afficherMatricule() se contente d'afficher la valeur de la variable matricule, d'autres méthodes comme, par exemple, la méthode afficherAge() devraient effectuer un certain nombre d'opérations pour pouvoir mener à bien leur tâche. Il s'agirait probablement (suivant le modèle choisi pour le reste de notre programme) d'interroger un objet pour connaître la date du jour, effectuer une soustraction (date du jour moins date de naissance), puis une série de conversions afin d'afficher l'âge.

Les membres statiques

Il semble aller de soi que le matricule d'un employé soit une caractéristique de cet employé, et non une caractéristique de sa classe. Cependant, la

diffé-rence n'est pas toujours aussi évidente. Si nous créons une classe Chien étendant la classe Animaux, nous pouvons attribuer à la classe Chien une variable nombreDePattes. Il est cependant probable que cette variable aura la valeur 4 pour toutes les instances de Chien. En effet, tous les animaux n'ont pas quatre pattes, mais tous les chiens ont quatre pattes. Il serait donc inutile que chaque instance de Chien possède cette variable. Il suffit qu'il partage l'usage d'une variable commune à toute la classe. Ce type de varia-ble est dit statique. Le terme correspondant en Java est static.

Note : Si le problème à traiter vous oblige à prendre en compte le fait qu'un chien puisse n'avoir que trois, deux, une seule ou même aucune patte, il vous suffira de créer la variable statique nombreNormalDePattes et une variable non statique nombreDePattes. Il vous sera alors possible de définir une méthode estropié() qui retournera la valeur faux si les variables nombreDePattes et nombreNormalDePattes ont des valeurs différentes, et vrai dans le cas contraire.

Dans le cas de notre classe Employé, nous supposerons que nous utilise-rons comme matricule le numéro d'ordre de l'employé. Le premier employé créé aura le numéro 1, le deuxième le numéro 2, etc. Le problème qui se pose est alors de garder en mémoire le numéro du dernier employé créé. La solution consiste à ajouter une variable statique. Notre classe Employé de-vient alors :

Objet

Employé

static nombre variables :

matricule méthode :

afficherMatricule()

Le matricule est propre à chaque employé (chaque instance d'Employé). La variable statique nombre est propre à la classe Employé. (Nous l'avons

ap-pelée nombre au lieu de numéro, car, dans le cadre de notre problème, le numéro attribué correspond au nombre d'employés. Bien sûr, dans la vie réelle, cela se passe rarement de cette façon, car des employés peuvent être supprimés sans que leurs numéros soient réaffectés.)

Les constructeurs

Vous vous demandez peut-être comment on fait pour créer une instance à partir d'une classe ? C'est très simple. Il suffit, pour cela, de faire appel à un constructeur.

Un constructeur est une méthode qui a pour particularité de posséder le même nom que la classe à laquelle il appartient. Si l'usage typographique de Java est respecté, il est donc très facile de distinguer un constructeur d'une méthode ordinaire : sa première lettre est en majuscule. (Il est égale-ment facile de le distinguer du nom de la classe à laquelle il appartient, puisqu'il est suivi de parenthèses encadrant ses éventuels arguments.) Voyons comment pourrait se présenter un constructeur pour notre classe Employé. Pour créer un employé, il faut lui attribuer un matricule. Pour cela, il suffira d'interroger la classe pour connaître le nombre d'employés, d'augmenter ce nombre d'une unité et d'utiliser le résultat comme matricule.

Voici à peu près ce que cela pourrait donner :

class Employé extends Object { int matricule;

static int nombre;

Employé() {

matricule = ++nombre;

}

void afficherMatricule() {

System.out.println(matricule);

} }

Nous avons ici écrit explicitement que la classe Employé étend la classe Object, ce qui n'était pas nécessaire, puisque nous avons vu précédemment que toutes les classes étendent par défaut la classe Object. Nous aurions pu tout aussi bien écrire :

class Employé {

Penchons-nous maintenant sur la deuxième ligne. Dans celle-ci, nous dé-clarons notre première variable. Ce sera un nombre entier (int). Le nom que nous lui donnons est matricule.

int matricule;

La troisième ligne fait exactement la même chose en déclarant une variable entière appelée nombre.

static int nombre;

Comme nous avons employé le mot static, il n'existera qu'un seul exem-plaire de cette variable, qui appartiendra à la classe Employé et non à ses instances.

Attention : Tout ce que nous venons de décrire est très particulier. En effet, les variables de type int ne sont pas des objets ordinaires. Nous ne pouvons en dire plus pour le moment. Tout cela deviendra clair au prochain chapitre.

On trouve ensuite la définition du constructeur de la classe Employé :

Employé() {

matricule = ++nombre;

}

A la première ligne, nous déclarons une méthode. Cette déclaration com-porte le nom de la méthode et les paramètres qu'elle emploie. Le nom étant identique à celui de la classe à laquelle la méthode appartient, nous savons qu'il s'agit d'un constructeur. Cette méthode sera donc exécutée automati-quement par Java lorsque nous créerons une instance (un objet) de la classe

Employé. De plus, s'agissant d'un constructeur, cette méthode ne possède pas d'indication de type de valeur de retour. Entre les parenthèses se trouve la liste des arguments, ou paramètres, de la méthode. Chaque argument est composé d'un nom de classe et d'un nom d'instance, séparés par un espace.

S'il y a plusieurs arguments, ils sont séparés par des virgules. Ici, nous n'uti-lisons aucun argument.

La déclaration de la méthode se termine par une accolade ouvrante qui ouvre un bloc. Ce bloc contient la définition de la méthode. Il se termine par une accolade fermante, à la quatrième ligne.

La déclaration ne comporte qu'une seule ligne :

matricule = ++nombre;

Sa signification (simplifiée) est : "Augmenter d'une unité la valeur de nom-bre et attribuer cette valeur à matricule."

Il faut bien comprendre que cette ligne fait deux choses différentes :

Elle augmente la valeur de nombre ;

Elle attribue la valeur de nombre à matricule.

Cela est tout à fait différent de la ligne suivante :

matricule = (nombre + 1);

qui attribuerait bien la valeur de nombre + 1 à matricule, mais laisserait nombre inchangé.

Nous avons ajouté ensuite une méthode qui affiche le matricule à l'aide de ce que nous avons étudié au chapitre précédent. Cette méthode n'étant pas un constructeur, elle doit être précédée de l'indication du type de valeur qu'elle fournit. Cette valeur est appelée valeur de retour. Cette méthode ne retourne aucune valeur. Il existe pour cela, comme nous l'avons vu au cha-pitre précédent, un type particulier : void, qui signifie "rien" ou "aucune valeur".