• Aucun résultat trouvé

1 Un langage plutˆ ot classe

Java est un langage objet avec des classes. Les classes ont une double fonction : structurer les programmes et dire comment on construit les objets. Pour ce qui est de la seconde fonction, il n’est pas si facile de d´efinir ce qu’est exactement un objet dans le cas g´en´eral. Disons qu’un objet poss`ede un ´etat et desm´ethodes qui sont des esp`eces de fonctions propres `a chaque objet.

Par exemple tous les objets poss`edent une m´ethode toString sans argument et qui renvoie une chaˆıne repr´esentant l’objet et normalement utilisable pour l’affichage. La section 2 d´ecrit la construction des objets `a partir des classes.

Mais d´ecrivons d’abord la structuration des programmes r´ealis´ee par les classes. Les classes regroupent des membres qui sont le plus souvent des variables (plus pr´ecis´ement des champs) et des m´ethodes, mais peuvent aussi ˆetre d’autres classes.

1.1 Programme de classe

Un programme se construit `a partir de une ou plusieurs classes, dont une au moins contient une m´ethodemain qui est le point d’entr´ee du programme. Les variables des classes sont les va-riables globales du programme et leurs m´ethodes sont les fonctions du programme. Une variable ou une m´ethode qui existent d`es que la classe existe sont ditesstatiques.

Commen¸cons par un programme en une seule classe. Par exemple, la classe simple suivante est un programme qui affiche Coucou !sur la console :

class Simple {

static String msg = "Coucou !" ; // d´eclaration de variable public static void main (String [] arg) // d´eclaration de m´ethode {

System.out.println(msg) ; }

}

Cette classe ne sert pas `a fabriquer des objets. Elle se suffit `a elle mˆeme. Par cons´equent tout ce qu’elle d´efinit (variable msg et m´ethode main) est statique. Par re-cons´equent, toutes les d´eclarations sont pr´ec´ed´ees du mot-cl´e static, car si on ne met rien les membres ne sont pas statiques. Si le source est contenu dans un fichier Simple.java, il se compile par javac Simple.java et se lance parjava Simple. C’est une bonne id´ee de mettre les classes dans des fichiers homonymes, ¸ca permet de s’y retrouver.

En termes de programmation objet, la m´ethodemaininvoque la m´ethodeprintln de l’objet System.out, avec l’argument msg.System.out d´esigne la variable outde la classe System,

173

qui fait partie de la biblioth`eque standard de Java. Notons que msg est en fait Simple.msg, mais dans la classe Simple, on peut se passer de rappeler quemsg est une variable de la classe Simple, alors autant en profiter.

Reste `a se demander quel est l’objet rang´e dansSystem.out. Et bien, disons que c’est un objet d’une autre classe (la classePrintStream) qui a ´et´e mis l`a par le syst`eme Java et ne nous en pr´eoccupons plus pour le moment.

1.2 Compl´ement : la m´ethode main

La d´eclaration de cette m´ethode doit obligatoirement ˆetre de la forme : public static void main (String [] arg)

En plus d’ˆetre statique, la m´ethodemain doit imp´erativement ˆetrepublique (mot-cl´epublic) et prendre un tableau de chaˆıne en argument. Le sens du mot-cl´epublic est expliqu´e plus loin.

Le reste des obligations porte sur le type de l’argument demain(son nom est libre). Le tableau de chaˆıne est initialis´e par le syst`eme pour contenir lesarguments de la ligne de commande. De sorte que l’on peut facilement ´ecrire une commande echoen Java.1

class Echo {

public static void main (String [] arg) { for (int i = 0 ; i < arg.length ; i++) {

System.out.println(arg[i]);

} } }

Ce qui nous donne apr`es compilation :

% java Echo coucou foo bar coucou

foo bar

1.3 Collaboration de classe

La classe-programme Simple utilise d´ej`a une autre classe, la classe System ´ecrite par les auteurs du syst`eme Java. Pour structurer vos programmes, vous pouvez (devez) vous aussi ´ecrire plusieurs classes. Par exemple, r´ecrivons le programme simple `a l’aide de deux classes. Le message est fourni par une classeMessage

class Message {

static String msg = "Coucou !" ; }

Tandis que le programme est modifi´e ainsi : class Simple {

public static void main (String [] arg) { // d´eclaration de m´ethode System.out.println(Message.msg) ;

} }

Si on met la classeMessagedans un fichierMessage.java, elle sera compil´ee automatiquement lorsque l’on compile le fichierSimple.java(parjavac Simple.java). Encore une bonne raison pour mettre les classes dans des fichiers homonymes.

1echoest une commande Unix qui affiche ses arguments

1.4 M´efiance de classe

Lorsque l’on fabrique un programme avec plusieurs classes, l’une d’entre elles contient la m´ethodemain. Les autres fournissent des services, en g´en´eral sous forme de m´ethodes accessibles

`

a partir des autres classes.

Supposons que la classe Hello doit fournir un message de bienvenue, en anglais ou en fran¸cais.

On pourra ´ecrire.

class Hello {

private static String hello ;

static void setEnglish() { hello = "Hello!" ; } static void setFrench() { hello = "Coucou !" ; } static String getHello() { return hello ; }

static { setEnglish() ; } }

Classe utilis´ee par une nouvelle classe Simple. class Simple {

public static void main (String [] arg) { System.out.println(Hello.getHello()) ; }

}

La variable hello est priv´ee (mot-cl´e private) ce qui interdit son acc`es `a partir de code qui n’est pas dans la classe Hello. Une m´ethode getHello est donc fournie, pour pouvoir lire le message. Deux autres m´ethodes laissent la possibilit´e aux utilisateurs de la classe de s´electionner le message anglais ou le message fran¸cais. Enfin, le bout de code static { setEnglish() ; } est ex´ecut´e lors de la cr´eation de la classe en machine, ce qui assure le choix initial de la langue du message. Finalement, la conception de la classe Hello garantit une propri´et´e : `a tout instant,

Hello.hello contient n´ecessairement un message de bienvenue en fran¸cais ou en anglais.

La pratique de restreindre autant que possible la visibilit´e des variables et m´ethodes am´eliore

`

a la fois la sˆuret´e et la structuration des programmes.

ˆ Chaque classe propose un service, qui sera maintenu mˆeme si la r´ealisation de ce service change. Il est alors moins risqu´e de modifier la r´ealisation d’un service. En outre, puisque seul le code de la classe peut modifier les donn´ees priv´ees, on peut garantir que ces donn´ees seront dans un certain ´etat, puisqu’il suffit de contrˆoler le code d’une seule classe pour s’en convaincre.

ˆ La structure des programmes est plus claire car, pour comprendre comment les diverses classes interagissent, il suffit de comprendre les m´ethodes (et variables) export´ees (i.e., non-priv´ees) des classes. En fait il suffit normalement de comprendre les d´eclarations des m´ethodes export´ees assorties d’un commentaire judicieux.

On parle d’abstraction, la s´eparation en classe segmente le programme en unit´es plus petites, dont on n’a pas besoin de tout savoir.

A l’int´erieur de la classe elle-mˆeme, la d´emarche d’abstraction revient `` a ´ecrire plusieurs m´ethodes, chaque m´ethode r´ealisant une tˆache sp´ecifique. Les classes elle-mˆemes peuvent ˆetre regroup´ees enpackages, qui constituent une nouvelle barri`ere d’abstraction. La biblioth`eque de Java, qui est ´enorme, est structur´ee en packages.

Le d´ecoupage en packages, puis en classes, puis en m´ethodes, qui interagissent selon des conventions claires qui disent le quoi et cachent les d´etails du comment, est un fondement de la bonne programmation, c’est-`a-dire de la production de programmes compr´ehensibles et donc de programmes qui sont (plus) facilement mis au point, puis modifi´es.

Il y a en Java quatre niveaux de visibilit´e, du plus restrictif au plus permissif.

ˆ private : visible de la classe.

ˆ Rien : visible du package.

ˆ protectedvisible du package et des classes qui h´eritent de la classe (voir ci-dessous).

ˆ public: visible de partout.

Nous connaissons d´ej`a quelques emplois de public.

ˆ Toutes les classes dont les sources sont dans le r´epertoire courant sont membres d’un mˆeme package implicite. La classe qui initialise le syst`eme d’ex´ecution de Java, puis lance le programme de l’utilisateur, n’est pas membre de ce package. Il est donc logique que main soit d´eclar´ee public. Noter que d´eclarer public les autres m´ethodes de vos classes n’a aucun sens, `a moins d’ˆetre train d’´ecrire un package.

ˆ La d´eclaration compl`ete de la m´ethodetoStringdes objets est public String toString() ;

Et c’est logique, puisqu’il est normal de pouvoir afficher un objet de n’importe o`u dans le programme.

ˆ Quand vous lisez la documentation d’une classe de la biblioth`eque (par exempleString) vous avez peut ˆetre d´ej`a remarqu´e que tout est public (ou tr`es rarement protected).

1.5 Reproduction de classe par h´eritage

La plus grande part de la puissance de la programmation objet r´eside dans le m´ecanisme de l’h´eritage. Comme premi`ere approche, nous examinons rapidement l’h´eritage et seulement du point de vue de la classe. Soit une classeFoo qui h´erite d’une classeBar.

class Foo extends Bar { . . .

}

La classe Foo d´emarre dans la vie avec toutes les variables et toutes les m´ethode de la classe Bar. Mais la classe Foo ne va pas se contenter de d´emarrer dans la vie, elle peut effectivement

´etendre la classe dont elle h´erite en se donnant de nouvelles m´ethodes et de nouvelles variables.

Elle peut aussi red´efinir les m´ethodes et variables h´erit´ees. Par exemple, on peut construire une classe HelloGoodBye qui offre un message d’adieu en plus du message de bienvenue de Hello, et garantit que les deux messages sont dans la mˆeme langue.

class HelloGoodBye extends Hello { private static String goodbye ;

static void setEnglish() { Hello.setEnglish() ; goodbye = "Goodbye!" ; } static void setFrench() { Hello.setFrench() ; goodbye = "Adieu !" ; } static String getGoodBye() { return goodbye ; }

static { setEnglish() ; } }

On note que deux m´ethodes sont red´efinies (setEnglish et setFrench) et qu’une m´ethode est ajout´ee (getGoodBye). La m´ethode setEnglish ci-dessus doit, pour assurer la coh´erence des deux messages, appeler la m´ethode setEnglishde la classe Hello, d’o`u l’emploi d’une notation compl`ete Hello.setEnglish.

Comme d´emontr´e par la nouvelle et derni`ere classe Simple, la classeHelloGoodBye a bien re¸cu la m´ethode getHello en h´eritage.

class Simple {

public static void main (String [] arg) {

System.out.println(HelloGoodBye.getHello()) ; System.out.println(HelloGoodBye.getGoodBye()) ; }

}

En fait, l’h´eritage des classes n’a que peu d’int´erˆet en pratique, l’h´eritage des objets est bien plus utile.