Java - Rudiments d`objets

publicité
Java - Rudiments d’objets
Ca y est, nous allons enfin rentrer dans le vif du sujet. Java a été développé en partie pour créer un nouveau langage
objet. Mais bon, le problème pour l’instant c’est que vous ne savez pas ce qu’est l’objet, l’intérêt développé, ainsi
que l’usage courant que l’on peut en avoir. C’est pourquoi je fais ici, un petit chapitre d’introduction à ce nouveau
concept de programmation. Une fois que vous aurez compris ce principe là, vous pourrez à ce moment, commencer
à comprendre un code Java (dans le vrai sens, car pour l’instant vous ne savez pas ce que veut dire une classe, un
constructeur, une interface et bien d’autres choses).
1
Un objet ? Quoi ? Introduction du vocabulaire
L’objet, voila un sujet bien remis en cause depuis Java. Il fut introduit (d’après mes souvenirs) par le langage Ada,
grand précurseur de l’objet. L’intérêt était là, mais les applications faibles, depuis Java, beaucoup d’autres implémentations ont commencé à se développé, on rencontrera notamment Eiffel 95, Python et une version objet du bien connu
CaML. Entrons maintenant dans le vif du sujet.
L’objet a bien choisit son appellation, un objet, en soi, est un truc, un machin, un objet, que vous pouvez rencontrer
tout les jours, une chaise, un arbre, une machine à café. Ca y est, le WydD, il a pété un cable. Et bien non, c’est
exactement ça. Un objet, qu’a-t-il comme propriétés ? Il a des paramètres bien à lui, par exemple pour un cube, la taille
d’un de ses cotés. Ces variables s’appelleront les attributs de l’objet. Mais un objet, en soi, peut savoir (ce n’est pas
obligatoire) faire des choses, une machine à café sait servir du café. Ces fonctionnalitées seront appellées méthodes.
Le but de la POO, est de matérialiser ces objets, avec attributs et méthodes, et chaque objet pourra être interpréter en
tant que variable (c’est un barbarisme je sais mais c’est pour montrer comment on les manipule).
Plusieurs objets peuvent appartenir à un même ensemble d’objet. Je m’explique, si on prend un cube de 2cm de
coté, et un autre de 5cm de coté, ces deux objets sont tous deux des cubes. On appelle donc l’objet maître, cet ensemble,
une classe. Ah ! Ca y est vous savez ce qu’est une classe ! Passons à la vitesse supérieure.
Vous avez votre classe, et vous voulez créer un objet, suivant plusieurs paramètres (voire un seul, voire aucun). Par
exemple, vous voulez un cube (encore lui ?) de 2cm de coté, vous allez appeler M. Cubeman, qui va vous fabriquer
votre cube (au moyen d’une petite rétribution qu’en programmation ne se traduira que par de l’emplacement mémoire).
Ce M. Cubeman, s’appellera le constructeur de la classe des cubes, et le cube fabriqué sera appellé une instance de la
classe cube.
Voila, vous avez le vocabulaire principal relatif à l’objet. Voyons maintenant l’implémentation que l’on obtient en
Java.
2
L’implémentation Java
Ne tournons pas autour du pot, je vous ai déjà bassiné avec mon vocabulaire :
1
2
3
public class Cube { // Création de la classe des cubes
// attributs
public int cote;
4
5
6
7
8
// Constructeur (Monsieur Cubeman)
public Cube(int un_cote) {
cote = un_cote;
}
9
10
11
12
13
14
15
16
17
// Méthodes
public int surface() {
return 6*cote*cote;
}
public int volume() {
return cote*cote*cote;
}
public void changerCote(int nouveau_cote) {
1
cote = nouveau_cote;
18
}
19
20
// fin de la déclaration de classe
21
}
22
Je suppose que le code parle de lui même. Notez que devant chaque déclaration d’attribut, de constructeur, de
méthodes et de classe, vous pouvez bien évidemment toujours utiliser les mots clefs public, private et protected. On
utilisera très très courament le public (et plusieurs fois des private, protected est beaucoup plus rare). On évitera de
laisser une déclaration sans mot clef d’accès.
Dans le constructeur, on a tous les élements pour initialiser notre cube, la construction se fait de façon très native,
ici on a qu’à stocker la valeur de la cote. Attention, le constructeur n’est pas noté de façon anodine, il doit être déclaré
sans type (ce n’est pas une méthode, il n’a ni int, ni void, ni autre) et il doit être du même nom que la classe.
Remarquez aussi, que la surface n’est pas un attribut de la classe des cubes, ce n’est pas une propriété fondamentale
d’un cube. Mais on peut demander à un cube de nous donner sa surface, de même avec le volume. Un dernier petit
commentaire, un attribut n’est absolument pas fixe ! En effet, on peut créer une méthode changerCote qui peut déformer
le cube, afin qu’il devient un cube dont le coté sera changé, ce qui nous écarte de la réalité des choses mais nous fait
rentrer profondement dans la programmation, la liberté y est très prononcée. Notez que si nous le voulions, nous aurions
pu rendre la variable int cote constante.
Tout cela est bien beau, mais comment le manipuler ? Stockez le code que je vous ai décrit dans un fichier nommé
Cube.java (soit le nom de la classe, on est obligé de respecter cela du moment où l’on déclare une classe publique).
Maintenant, regardez bien mon Main.java :
public class Main {
public static void main(String args[]) {
Cube c = new Cube(2);
int volume = c.volume();
System.out.println("Le volume de mon cube c est de "+volume+"m2");
}
}
1
2
3
4
5
6
7
A la ligne 3, on créé un nouveau cube que l’on va appeller c, c est donc une instance de la classe Cube, on dira
de façon plus concrête que "c est un cube". Maintenant voyons la manipulation de l’objet c. On peut appeler chaque
attribut ou méthode par la structure :
- Appel d un attribut
instance.attribut
- Appel d une méthode
instance.methode(parametres)
1
2
3
4
5
Par exemple :
System.out.println(c.cote); //Affiche 2
c.changerCote(3);
System.out.println(c.cote); //Affiche 3
6
7
8
9
Notez que l’on peut accéder facilement à la cote car notre attribut ici est défini comme publique, tout accès est propre.
Le principe est maintenant mis en place, voyons quelques nouveaux concepts.
3
Le set/get
3.1
This
Lors de la déclaration de classe, comment pourrait-on faire pour s’appeller soi-même. Lorsque par exemple on
appelle une méthode d’une instance, comment faire à l’intérieur de la méthode pour récupérer l’instance que l’on
utilise. Pourquoi me diriez vous ? Imaginez une méthode en appelle une autre qui en paramètre demande une instance
de cube ? Mmmh ce n’est pas clair ... Un exemple vaut plus que des dixaines de lignes.
1
2
3
4
5
6
// Nous sommes ici dans la classe Cube
public void peindre() {
// Imaginez que l ’on a un module qui permet de peindre un cube
Module mod = new Module();
mod.drawCube( [instance demandée] );
}
Voila là où est notre this, dans le code, l’instance demandée est le mot clef this. Ainsi on a :
2
1
mod.drawCube(this);
Là aussi le vocabulaire est très bien choisi puisque this en anglais veut dire "ceci".
Voyons maintenant THE application, le fondement principal de la structure de l’objet.
3.2
Le set/get en soi
Lorsque l’on utilise l’objet, il y a des attributs internes et des attributs externes, i.e. des attributs qui n’intéressent
que l’objet en lui même, et d’autres que l’utilisateur veut visualiser ou modifier. Par exemple, le module d’affichage
de notre cube, il est intéressant de pouvoir modifier le titre de la fenêtre dans laquelle le cube sera affiché (ou encore
la taille de la fenêtre), et par contre, l’utilisateur se fout de savoir qu’un panel sera créé pour mettre le cube dedans,
pourtant il sera attribut.
La manipulation des attributs interne est souvent déclaré en tant que private, les externes en tant que public. Pour
récupérer ou modifier ces paramètres indépendaments de public et private on a la méthode du SET/GET. Pour chaque
attribut qu’il serait interessant de donner accès à l’extérieur, on peut créer deux méthodes, l’une SET (modifier), l’autre
GET (récupérer). Evidemment si l’on veut protéger un attribut en écriture, on ne créé pas de SET. Voyons sur notre
cube, déclaré tel qu’un vrai programmeur ferait :
1
2
3
4
5
6
7
8
9
10
11
12
public class Cube {
public int cote;
public Cube(int cote) {
this.cote = cote;
}
public void setCote(int cote) {
this.cote = cote;
}
public int getCote(int cote) {
return cote;
}
}
Voila une des principales implémentations du this. A la ligne 4, on a this.cote qui représente le cote pur de l’objet,
et cote qui représente le paramètre passé au constructeur Cube. Le set est exactement pareil, mais lui ne crée pas, il
modifie juste l’attribut. Le get lui renvoi l’attribut cote, la différence avec c.cote ? A priori aucune, mais il y a deux
avantages. Tout d’abord il structure beaucoup plus le code, on sait quand on appelle un get, que l’on veut récupérer la
valeur de l’attribut. Et ensuite, il est indépendant de la déclaration public.
4
Statique et Dynamique
Dans la manipulation d’objet, la première chose que l’on fait, c’est la création d’une instance. Seulement, une classe
peut être vue comme un module, un plug-in, qui en soit est évidemment un objet (de toute façon, tout est objet). Sans
créer l’instanciation, i.e. sans l’initialiser, un module peut avoir des fonctions concrêtes. Un exemple ? Il y en a bien
que vous avez déjà manipulé, Integer.parseInt par exemple ? Integer est bien une classe, on peut en créer une instance
(vous pourrez voir ce qu’il en retourne dans l’API d’ailleurs), mais on peut appeler sans instance la fonction parseInt.
On dit que la fonction parseInt est statique.
Dans notre cube, on ne peut dire que la fonction surface est statique, puisque Cube.surface() n’aurait AUCUN
sens, on demanderait la surface, oui mais de quoi ? Evidemment il n’y a pas que les fonctions qui ont le monopole de
la capacité à être statique, les attributs peuvent l’être, évidemment System.out est un attribut statique (certes c’est un
peu tordu car out est un flux, chut je n’ai rien dit). Par contre les attributs statiques doivent être initialisés dans leur
déclaration (évidemment il faut bien retourner quelque chose non ?).
Pourquoi statique ? Tout simplement parce que la situation d’une méthode statique ne changera pas au cours du
temps, pareil pour les variables statiques, la prochaine fois qu’on les appelera, le processus sera remis à zéro et on
continuera. Ca tous les langages peuvent utiliser ce principe !
La dynamique c’est justement quelque chose qui pourra fluctuer au cours du temps, voyez le simple getCote.
Appelez une fois getCote, faites un coup de setCote, et réappellez getCote, il a changé de valeur, pourtant c’est toujours
la même méthode ... Voila une des puissances de l’objet, vous ne manipulez pas UNE variable, vous manipulez un
ENSEMBLE que l’on appelle Objet.
Petite précision, lorsque l’on déclare une méthode statique, tous les attributs et méthodes appellés doivent être
obligatoirement statiques. C’est évident car une méthode statique ne peut faire appel à une structure dynamique, elle
serait donc dynamique par définition.
Maintenant, que l’on sait ce qu’est le statique, illustrons tout cela par un petit exemple.
3
1
2
3
4
5
6
7
1
// dans la classe Cube
public static String surface_calc() {
return "6 x coté ^ 2";
}
public static String volume_calc() {
return "coté ^ 3";
}
On peut maintenant appeler ces méthodes par le classique :
Cube.volume_calc();
Sans créer d’instance, on peut donc appeller ces variables / méthodes.
Petite application : HelloWorld. Pourquoi faire
1
public static void main
1
public static void main(String args[]) {
new HelloWorld();
}
La classe HelloWorld (ici) ne nous intéresse pas en soi ! Nous n’avons pas besoin de créer un objet pour lancer HelloWorld. L’executeur, lorsqu’on lui demande le fameux java HelloWorld, lance la commande HelloWorld.main(args),
car (pour l’instant) il est inutile de créer l’objet HelloWorld. Remarquez que cela ne sera pas toujours le cas, par la
suite on préfèrera souvent construire l’objet en lançant dans le main
2
3
5
Exemple concret - Objet très utile
Pour l’instant, on a pas la notion d’héritage, donc les exemples sont assez restreints, mais on peut tout de même
montrer la puissance de l’objet très facilement.
Imaginez que vous concevez un jeu de Football, vous créez les classes suivantes (je ne le programme pas de suite,
nous l’approfondiront au chapitre suivant) : Joueur, Coach, Terrain et Balle. A chaque classe vous allez doter chacun
d’une pseudo-intelligence. Premierement vous créez un terrain, qui est modélisé par un rectangle de taille définie, et
une balle qui aura pour attribut le terrain créé, ainsi que sa position. Maintenant vous créez un entraineur, celui-ci sera
chargé de recruter (créer des joueurs) et de manipuler les joueurs. Ainsi, le joueur aura comme attributs le coach, le
terrain, la balle et bien sûr sa position.
Au niveau des méthodes, le joueur sait frapper dans une balle avec une intensité donnée (je fais ça de façon primitive) et de se déplacer sur le terrain, le coach saura donner tous les ordres aux joueurs comme : tous en avant, en
défensive ... Bien entendu les méthodes du terrain et de la balle sont négligeable.
Voyez que la manipulation se fait de façon très intuitive, et la programmation statique d’un tel jeu est plus complexe,
mais évidement, rien ne se pert, rien ne se crée, tout se paye ! (ah c’est pas ça ?) Le cout mémoire de la création de tels
objets est plus lourd qu’un jeu fait en statique avec des tableaux. C’est pour cela que l’on trouve les programmes java
lents. Mais cela tend à l’amélioration je vous rassure ! !
6
Conclusion
Voila qui conclut ce chapitre de rudiments d’objets. C’est complexe, j’en suis conscient, enfin disons plutôt que
c’est difficile à comprendre, à assimiler, une fois cette étape franchie, la POO devient naturelle. Pourquoi l’ai-je fais si
rapidement ? Tout simplement parce que la compréhension des programmes et des exemples qui vont suivre seront très
flous sans ça. Vous l’avez déjà remarqué avec le mot clef "static" et bien sûr "class" que l’on a plusieurs fois rencontré
mais que l’on ne savait expliquer. J’espère que cela n’est pas trop trop flou pour vous, mais qui veut programmer en
java doit comprendre l’existence d’un objet. Pourquoi rudiments d’objet ? Parce que là nous n’avons vu que la face
émergée de l’iceberg. Maintenant que l’on sait ce qu’est un objet nous pouvons voir en détail ce qu’est un héritage, une
interface ainsi que plusieurs méthodes et applications de l’objet, c.f. chapitre 4.
J’ai mis deux jours à écrire cet article sachant que je suis en vacances théoriquement, j’espère qu’il sera assez clair,
pour toute question, suggestion, engueulade voire commande de pizzas ( ? ? ?) je suis à votre entière disposition !
4
Téléchargement