Upload
others
View
3
Download
0
Embed Size (px)
Citation preview
Programmation en Java
V.Padovani, PPS, Paris-Diderot
Programmation en Java 1
PARTIE I - Classes et Objets
• Eléments ommuns à C et Java
• Classes, objets et référenes
• Initialisation des objets : les onstruteurs
• Modi�ation des objets : les méthodes.
Programmation en Java 2
1. De C à Java
1.1. Eléments de base du langage
éléments ommuns à C et Java :
• notions de variable, de typage, d'a�etation,
• types numériques int, float, double, et.
• opérateurs arithmétiques + *, -, /, ++, �-, et.
• opérateurs de omparaison ,
• onditions, onneteurs ||, &&, !,• strutures if/else, for, while, do/while, swith,
• ?/:, break, ontinue
les variables se délarent à la volée (6= C ANSI).
Programmation en Java 3
• un type boolean de onstantes true, false.
int x, y = 10, z = 20;
boolean b = (x == 3) && (y + 10 < z);
• Les onditions doivent être de type booléen :
if (x != 0) { ... } // et non if (x), omme en C.
• Un for peut avoir un ompteur loal :
for (int i = 0; i < n; i++) {
// i delare et visible seulement
// dans le orps de la boule,
}
Programmation en Java 4
1.2. Syntaxe des tableaux
• délarés et rées :
� à l'aide de l'opérateur new :
int[℄ t = new int[100℄;
� ou par desription expliite :
int[℄ u = {2,3,0,1};
même syntaxe d'a
ès qu'en C : t[i℄ = 42; et.
• int[℄ est le type des tableaux d'entiers.
• Les tableaux sont gratuitement initialisés à 0.
Programmation en Java 5
• la taille des tableaux est libre (plus de mallo/free) :
double[℄ t = new double[n + 42℄;
• t.length vaut le nombre d'éléments de t.
• les a
ès sont véri�és à l'exéution.
les a
ès invalides interrompent l'exéution.
har[℄ t = new har[100℄;
/** t[-1℄ = 'a'; // erreur d'exeution
* t[100℄ = 'a'; // erreur d'exeution
*/
Programmation en Java 6
1.3. A�hage
• équivalents de printf :
� System.out.print
� System.out.println (retour à la ligne)
• plus besoin de spéi�ateurs de format :
for (int i = 0; i < 10; i++) {
System.out.print("le arre de");
System.out.print(i);
System.out.print(" est ");
System.out.println(i * i);
}System.out.println('a');
System.out.println(3.14); // et.
Programmation en Java 7
• System.out.print ou System.out.println peuvent
prendre plusieurs arguments séparés par des +...
for (int i = 0; i < 10; i = i++)
System.out.println
("le arre de " + i + " est " + (i * i));
• l'assoiation des + s'e�etue de gauhe à droite.
entre deux valeurs numériques, + garde le sens de �addition�.
int i = 2;
System.out.println(i + i); // affihe 4.
System.out,println(i + " " + i) // affihe 2 2
System.out,println(i + i + " " + i) // affihe 4 2
Programmation en Java 8
• il existe un type String pour les haînes de aratères.
+ est l'opérateur de onaténation des haînes. on peut onaténer
une haîne et une valeur numérique, onvertie dans e as en String.
String s = "ab";
System.out.println(s); // affihe "ab"
s = s + "def";
System.out.println(s); // affihe "abdef"
s = s + 42;
System.out.println(s); // affihe "abdef42"
// et.
• un argument numérique de println sera onverti en String
(String est une lasse et les haînes sont des objets, sens à préiser).
Programmation en Java 9
1.4. Hiérarhie des types de base et onversions
• boolean (true, false)
• byte (8 bits, signé)
• har (16 bits, non signé) (i.e. jeu de aratères étendu)
• short (16 bits, signé)
• int (32 bits, signé)
• long (64 bits signé)
• float
• double
Programmation en Java 10
• les onversions vers un type plus petit doivent toujours être expliites.
/* erreur à la ompilation
* int x = 1;
* har = 'a' + x; // 'a' promu en int et
* // somme en int, pas har
*/
/* orret. d vaut 'b' */
int x = 1;
har d = (har) ('a' + x); // somme onvertie en har.
Programmation en Java 11
/* erreur à la ompilation. 2.5f n'est pas dans
* les valeurs du type int :
* int x = 2.5f;
*/
/* orret. x vaut l'arrondi 2 */
int x = (int) 2.5f;
• les onversions véri�ables dès la ompilation sont inutiles :
/* orret : la valeur 'b' assignée à peut être
* pré-alulée dès la ompilation, et ette valeur
* reste dans les limites du type har */
har e = 'a' + 1;
Programmation en Java 12
• ++ et �- opèrent sans onversions :
har = 'a';
++;
/* vaut 'b' */
har d = 'a';
/* erreur ! d promu en int, d + 1 en int
* d = d + 1;
*/
/* orret */
d = (har) d + 1;
Programmation en Java 13
2. Objets, Classes et Référenes
2.1. Des strutures de C aux lasses de Java
• objet ≡ une généralisation de la notion de struture en C.
• omme une struture C, un objet
� enapsule des données désignées par des noms de hamps,
� est réé suivant un ertain modèle dé�ni à l'avane.
modèle d'objet ≡ lasse de et objet.
objets d'une lasse ≡ instanes de ette lasse.
• un programme Java est suite de délarations de lasses.
Programmation en Java 14
// fihier exemple.
// delaration d'un nouveau type de struture
strut point2D { // modele de struture a deux hamps
int abs; // de type int, indefinis par defaut
int ord;
};
// fontion prinipale du fihier (lanee a l'exeution)
int main(int arg, har *argv[℄) {
strut point2D *p; // delaration de pointeur
// vers strut point2D
p = mallo(sizeof(strut point2D)); // alloation, stokage de
// l'adresse allouee dans p
(*p).abs = 42; // a
es aux hamps via p
(*p).ord = 10;
free(p);
return 0;
}
Programmation en Java 15
// fihier Exemple.java (meme nom que la lasse prinipale)
// delaration d'une nouvelle lasse Point2D
lass Point2D { // modele d'objet a deux hamps
int abs; // de type int, valeurs par defaut 0
int ord;
}// delaration de la lasse prinipale du fihier
publi lass Exemple {
// "fontion" prinipale du fihier (lanee a l'exeution)
publi stati void main(String[℄ args) {
Point2D p; // delaration d'une referene (pointeur)
// vers les objets de la lasse Point2D
p = new Point2D(); // reation d'une instane de Point2D
// stokage de son adresse dans p
p.abs = 42; // a
es aux hamps de l'objet via
p.ord = 10; // la referene p.
}
}
Programmation en Java 16
• les valeurs de hamps sont nulles à la réation d'un objet,
sauf si l'on spéi�e expliitement d'autres valeurs :
lass Point2D {
int abs = 10; // valeur par defaut pour haque instane ree
int ord; // valeur nulle a la reation
}
Programmation en Java 17
2.2. Les référenes
• référene en Java :
� variable pouvant ontenir l'adresse-mémoire d'un objet
� similaire à un pointeur vers struture de C, mais
sans la notation * pour l'a
ès aux hamps.
• la lasse des objets sur lesquels pourra pointer une référene
est spéi�ée par sa délaration:
nom de lasse nom de référene;
Point2D p;
(auun objet réé, p est pour l'instant de valeur indé�nie).
• on peut donner à une référene la valeur nulle : p = null;.
Programmation en Java 18
2.3. Création et référenement des instanes
• réation d'une instane via new + nom de lasse :
Point2D p; // p de valeur indefinie
p = new Point2D(); // alloation d'un objet en memoire,
// retour de son adresse, stokage de
// ette adresse dans p
// p referene/designe/pointe a present vers l'objet ree
p.abs = 42; // a
es aux hamps de l'objet
p.ord = 10; // via la referene p.
Programmation en Java 19
• deux référenes peuvent référener le même objet :
Point2D p, q;
p = new Point2D(); // nouvel objet, referene par p
q = p; // p et q referenent a present le meme objet
p.abs = 42; // a
es a l'objet via p
q.ord = 10; // a
es au meme objet via q
System.out.println(" p.abs = " + p.abs); // 42
System.out.println(" p.ord = " + p.ord); // 10
System.out.println(" q.abs = " + q.abs); // 42
System.out.println(" q.ord = " + q.ord); // 10
Programmation en Java 20
• une même référene peut pointer vers plusieurs objets au ours du temps :
Point2D p = new Point2D(); // une 1ere instane reee
p = new Point2D(); // une 2nde instane reee
La 1ère instane réée est dé�nitivement perdue.
• pas de fuite de mémoire : les objets qui ne sont plus référenés seront
t�t ou tard e�aés de la mémoire ("garbage olleting" automatique).
Programmation en Java 21
• les hamps d'un objet peuvent être de type référene :
lass Point2D {
int abs; // valeurs par defaut : 0
int ord;
}
lass Segment {
Point2D debut; // valeurs par defaut : null
Point2D fin;
}la réation d'un segment ne rée pas ses extrémités :
il faut deux new supplémentaires par segment...
Programmation en Java 22
Segment s = new Segment();
// pour l'instant, s.debut et s.fin valent null.
// reation des extremites et ablage :
Point2D p1 = new Point2D();
Point2D p2 = new Point2D();
s.debut = p1; // s.debut et p1 designent le meme objet
s.fin = p2; // s.fin et p2 designent le meme objet
// reation direte des extremites :
Segment t = new Segment();
t.debut = new Point2D();
t.fin = new Point2D();
Programmation en Java 23
• on peut forer la réation des extrémités via l'initialisation des hamps :
lass Segment {
Point2D debut = new Point2D(); // (re)-evalues à haque
Point2D fin = new Point2D(); // reation de segment.
}//...
Segment s = new Segment(); // un segment et deux points rees !
Segment t = new Segment(); // un segment et deux points rees !
// et.
Programmation en Java 24
2.4. Remarques
• on onfond souvent objet et référene vers objet :
� "l'objet référené par p", ou
� "l'objet p"
� "le point 2D p"
• une référene ontient en fait plus d'information qu'un pointeur :
Point2D p = new Point2D();
System.out.println(p);
a�he e.g. Point2D�defa1a (lasse + adresse).
Programmation en Java 25
3. Initialisation d'Objets : les Construteurs
3.1. Délarations de onstruteurs
• onstruteur ≡ ode d'initialisation plaé dans une délaration de lasse.
e ode peut être appelé au moment de la réation d'une instane.
• haque onstruteur porte le même nom que la lasse.
il peut avoir des paramètres.
lass Point2D {
int abs;
int ord;
Point2D() {} // onstruteur sans arguments
Point2D(int x, int y) { // onstruteur a deux arguments
abs = x; ord = y;
}
}
Programmation en Java 26
• l'appel d'un onstruteur ne peut se faire qu'ave un new, au moment
de la réation d'une nouvelle instane :
Point2D p = new Point2D(); // appel du 1er onstruteur
Point2D q = new Point2D(42, 10); // appel du 2nd.
• new Point2D(42, 10) :
1. réation (new) d'une nouvelle instane de Point2D
2. exéution de Point2D(int x, int y)
ave passage par valeur x ← 42, y ← 10, et
abs et ord désignant les hamps de l'objet réé en (1).
3. retour d'une référene vers l'objet réé.
Programmation en Java 27
lass Point2D {
int abs;
int ord;
Point2D() {}
Point2D(int x, int y) {
abs = x;
ord = y;
}
}
• odes équivalents :
� Point2D p = new Point2D();
p.abs = 42;
p.ord = 10;
� Point2D p = new Point2D(42, 10);
Programmation en Java 28
3.2. Construteur par défaut et délarations multiples
• sans onstruteurs délarés, la lasse est munie impliitement d'un
onstruteur par défaut (pas d'arguments, orps vide ne faisant rien).
lass Point2D {
int abs, ord;
}est équivalent à
lass Point2D {
int abs, ord;
Point2D() {} // pas d'arguments, et ne faisant rien.
}(d'ou le new Point2D() dans les exemples préédents)
Programmation en Java 29
• signature de onstruteur ≡ suite des types de ses paramètres.• on peut délarer autant de onstruteurs que l'on veut, pourvu
que leurs signatures soient distintes :
lass Point2D {
int abs;
int ord;
Point2D () {} // en () - et a delarer
Point2D (int x, int y) { // en (int,int)
abs = x; ord = y
}Point2D (Point2D p) { // en (Point2D)
abs = p.abs; ord = p.ord; // opie des hamps du point
} // passe en parametre
}
Programmation en Java 30
• Un onstruteur peut en appeler un autre par this(...) en
1ère instrution (pas néessairement unique) de e onstruteur.
lass Segment {
Point2D debut;
Point2D fin;
Segment() {
this(0,0,0,0); // appel du onstruteur
// en (int,int,int,int)
// ... et eventuellement, autres instrutions
}Segment(int x1, int y1, int x2, int y2) {
debut = new Point2D(x1, y1);
fin = new Point2D(x2, y2);
}
}
Programmation en Java 31
4. Modi�ations d'objets : les méthodes
4.1. Délarations de méthodes
• méthode ≡ ode plaé dans une délaration de lasse,
permettant la modi�ation des hamps de ses instanes
lass Point2D {
int abs;
int ord; // eventuellement des onstruteurs
// exemples de methodes :
void assigner(int x, int y) { abs = x; ord = y; }
void translater(int dx, int dy) {
abs = abs + dx;
ord = ord + dy;
}
}
Programmation en Java 32
4.2. Invoations de méthodes
• l'exéution d'une méthode se fait toujours relativement à un objet,
via une référene : on dit que la méthode est invoquée sur l'objet.
Point2D p = new Point2D();
p.assigner(42,10);
p.translater(20,20);
• p.assigner(42, 10) :
exéution de assigner(int x, int y)
ave passage par valeur x ← 42, y ← 10,
où dans le ode de la méthode,
abs et ord désignant les hamps de l'objet référené par p.
Programmation en Java 33
• une méthode peut renvoyer une valeur :
lass Point2D {
// ... hamps abs, ord, onstruteurs ...
Point2D loner() {
Point2D lone = new Point2D();
lone.abs = abs; // les hamps abs et ord de l'objet
lone.ord = ord; // ourant sont opies dans le lone
return lone;
}
}// ... et dans une autre partie du programme :
Point2D p = new Point2D(42,10);
Point2D q = p.loner(); // q est a present une opie de p
Programmation en Java 34
• une méthode peut invoquer une autre méthode (voire elle-même) :
lass Point2D {
// ... hamps abs, ord, onstruteurs ...
void assigner(int x, int y) {
abs = x;
ord = y;
}void reinitialiser() {
assigner(0,0); // invoquee sur l'objet ourant
}
}// ... et dans une autre partie du programme :
Point2D p = new Point2D(42,10);
p.reinitialiser(); // equivalent a : p.assigner(0,0)
Programmation en Java 35
• un onstruteur peut invoquer une méthode :
lass Point2D {
int abs;
int ord;
Point2D() {}
Point2D(int x, int y) {
assigner(x,y); // invoquee sur l'objet qui vient
} // d'etre ree par new.
void assigner(int x, int y) {
abs = x;
ord = y;
}
}
Programmation en Java 36
4.3. Surharge de noms de méthodes
• signature de méthode ≡ suite des types de ses paramètres.
• deux méthodes peuvent porter le même nom à ondition que leurs
signatures soient distintes. le nom de méthode est dit surhargé.
• lors de l'invoation, l'implémentation hoisie sera elle qui orrespond
à la suite des types des arguments fournis...
Programmation en Java 37
lass Point2D {
int abs;
int ord;
// ... onstruteurs ...
void assigner(int x, int y) {
abs = x;
ord = y;
}void assigner(Point2D p) {
abs = p.abs;
ord = p.ord;
}void assigner() {
abs = 0;
ord = 0;
}
}
Programmation en Java 38
• ...e qui permet aussi d'érire :
lass Point2D {
int abs;
int ord;
// ... onstruteurs ...
void assigner(int x, int y) {
abs = x;
ord = y;
}void assigner(Point2D p) {
assigner(p.abs, p.ord);
}void assigner() {
assigner(0,0);
}
}où les deux dernières méthodes en (Point2D) et en () appellent
la première en (int, int).
Programmation en Java 39
4.4. Référene à l'objet ourant : this
• this sans arguments dans une méthode ≡ une référene vers l'objet
sur lequel ette méthode est invoquée.
• this sans arguments dans un onstruteur ≡ une référene vers l'objet
qui vient d'être réé par new.
lass Point2D {
//... l'eriture suivante est usuelle :
Point2D(int abs, int ord) {
this.abs = abs; this.ord = ord;
}void set (int abs, int ord) {
this.abs = abs; this.ord = ord;
}
}
Programmation en Java 40
4.5. Champs vs méthodes et masquage de hamps
• tout hamp, onstruteur ou méthode préédé du mot-lef private
est ina
essible à l'extérieur de sa lasse.
• en pratique, on privilégie les invoations de méthodes, en délarant souvent
tous les hamps privés :
lass Point2D {
private int abs; // representation interne des donnees,
private int ord; // invisible depuis l'exterieur.
// onstruteurs + methodes d'a
es aux hamps
...
}... et les noms abs et ord deviennent inonnus à l'extérieur de la lasse
Point2D : il faut passer par les méthodes pour a
éder aux hamps.
Programmation en Java 41
4.6. Classe des points, version �nale
lass Point2D {
// hamps prives
private int abs;
private int ord;
// onstruteurs
Point2D() {}
Point2D(int abs, int ord) {
this.abs = abs;
this.ord = ord;
}// ...
Programmation en Java 42
// methodes d'a
es en leture : nom standard = getChamp
int getAbs() {
return abs;
}int getOrd() {
return ord;
}// ...
Programmation en Java 43
// methodes d'a
es en leture : nom standard = setChamp
void setAbs(int abs) {
this.abs = abs;
}void setOrd(int ord) {
this.ord = ord;
}void set(int abs, int ord) {
this.abs = abs;
this.ord = ord;
}void set(Point2D p) {
this.set(p.abs, p.ord) // this faultatif, mais ourant
}
}Programmation en Java 44
4.7. Conlusion
• une délaration de lasse ontient :
� des hamps servant au stokage des données internes de ses instanes,
� du ode d'initialisation plaé dans des onstruteurs, permettant
l'initialisation automatique des hamps lors de la réation d'instanes,
� du ode de gestion des données stokées dans les instanes de ette
lasse, plaés dans des méthodes, permettant de modi�er les données
internes d'un objet.
Programmation en Java 45
• en pratique, les hamps sont:
� ina
essibles (private),
� initialisés via les onstruteurs,
� modi�és via les méthodes.
i.e. l'utilisateur n'a a priori auune onnaissane de la
représentation interne des données, mais seulement de
l'e�et de l'invoation de tel ou tel onstruteur ou méthode.
Programmation en Java 46
PARTIE II - Héritage
Programmation en Java 47
5. Extensions de lasses
5.1. Prinipe de l'extension de Classe
• extension de lasse ≡ permet de dé�nir une nouvelle lasse
� à partir d'une lasse déjà érite,
� en réupérant les implémentations de ses méthodes,
� en modi�ant éventuellement ertaines d'entre elles,
� en ajoutant éventuellement d'autres hamps et méthodes
• objetifs :
� réutiliser du ode déjà érit,
� adapter une lasse générique à un besoin partiulier,
� érire plusieurs variantes d'une même lasse, en érivant une seule fois
le ode ommun à ses variantes.
Programmation en Java 48
5.2. Syntaxe de l'extension
lass Point2D {
int abs, ord;
void affiher() {
System.out.println (abs + " " + ord);
}
}... variante par extension (extends) : points olorés.
lass Point2DColore extends Point2D {
int ol;
void affiherCouleur() {
System.out.println (ol);
}
}
Programmation en Java 49
Point2DColore p = new Point2DColore();
p.abs = 10;
p.ord = 42;
p.ol = 255;
p.affiher(); // affihe 10 42
p.affiherCouleur(); // affihe 255
les instanes de Point2DColore disposent de tous les hamps et
méthodes délarés dans la lasse Point2D :
� la lasse Point2DColore hérite de es hamps et méthodes.
terminologie pour les liens de parenté :
� Point2DColore est une extension/une lasse héritìere de Point2D
� Point2D est une lasse parente/un anêtre de Point2DColore
Programmation en Java 50
5.3. Redé�nitions de méthodes
• Une extension peut redé�nir ertaines des méthodes de sa lasse parente :
lass Point2D {
int abs, ord;
void affiher() { // anienne implementation
System.out.println (abs + " " + ord);
}
}
lass Point2DColore extends Point2D {
int ol;
void affiher() { // nouvelle implementation
System.out.println (abs + " " + ord + " " + ol);
}
}
Programmation en Java 51
l'implémentation invoquée pour une instane donnée sera toujours
elle de sa lasse :
Point2D p = new Point2D()
p.abs = 23;
p.ord = 37
p.affiher(); // invoque l'implementation de
// la lasse Point2D : "23 17"
Point2DColore p = new Point2DColore();
p.abs = 10;
p.ord = 42;
p.ol = 255;
p.affiher(); // invoque l'implementation de
// la lasse Point2DColore : "10 42 255"
Programmation en Java 52
• Les méthodes de nouvelles signatures ajoutées à une extension
sont onsidérées omme nouvelles :
lass Point2D {
int abs, ord;
// methode set en (int, int)
void set(int abs, int ord) {
this.abs = abs; this.ord = ord;
}
}
lass Point2DColore extends Point2D {
int ol;
// nouvelle methode set en (int, int, int)
void set(int abs, int ord, int ol) {
set(abs, ord); // invoation du set en (int, int), herite.
this.ol = ol;
}
}
Programmation en Java 53
5.4. A
ès aux aniennes implémentations : super
• lorsqu'une méthode est redé�nie par une extension, son anienne
implémentation reste a
essible via super. + nom de méthode :
lass Point2D {
int abs, ord;
void affiher() { System.out.println (abs + " " + ord); }
}
lass Point2DColore extends Point2D {
int ol;
void affiher() { // nouvelle implementation
super.affiher(); // appel de l'anienne, puis
System.out.println (ol); // affihage supplementaire.
}
}
Programmation en Java 54
5.5. Appel impliite du onstruteur en () de la lasse parente
• par défaut, l'éxéution d'un onstruteur de Point2DColore est
préédée de elle du onstruteur en () de sa lasse parente.
lass Point2D {
int abs, ord;
Point2D() { System.out.println ("Point2D !"); }
}
lass Point2DColore extends Point2D {
int ol;
Point2DColore() {
// appel impliite de Point2D() avant l'instrution qui
// suit : new Point2DColore() affihe "Point2D !", puis
System.out.println ("Point2DColore !"); }
}...
Point2DColore p = new Point2DColore();
// affihe "Point2D !", puis "Point2DColore !"
Programmation en Java 55
• dans e as, un onstruteur en () doit être dé�ni dans la lasse parente.
l'erreur suivante est lassique :
lass Point2D {
int abs, ord; // pas de onstruteur en () ?!...
Point2D(int abs,int ord) {
this.abs = abs;
this.ord = ord;
}
}
lass Point2DColore extends Point2D {
int ol;
Point2DColore (int ol) { this.ol = ol }
}// erreur de ompilation ! le onstruteur de Point2DColore
// appelle impliitement Point2D(){}... non implemente.
Programmation en Java 56
5.6. Appel expliite d'un autre onstruteur
• un onstruteur de Point2DColore peut demander expliitement l'appel
d'un autre onstruteur que elui en () de sa lasse parente, via
� this (...) (.f. Partie I)
qui appelle le onstruteur de la même lasse spéi�é par les types
des arguments.
� super (...)
qui appelle le onstruteur de la lasse parente spéi�é par les types
des arguments.
• dans les deux as, l'appel doit être la première instrution du onstruteur,
et ette forme d'appel n'est pas renouvelable.
Programmation en Java 57
lass Point2D {
int abs, ord; // valeurs nulles par defaut
Point2D() {}
Point2D(int abs,int ord) {
this.abs = abs;
this.ord = ord;
}
}
lass Point2DColore extends Point2D {
int ol;
Point2DColore() {} // appel impliite de Point2D()
Point2DColore(int ol) {
this(0, 0, ol) // appel de Point2DColore(int, int, int)
}Point2DColore(int abs, int ord, int ol) {
super (abs, ord); // appel de Point2D(int, int)
this.ol = ol;
}
}
Programmation en Java 58
5.7. Héritage et masquage
• Les hamps masqués (par private) d'une lasse parente
ne sont pas hérités par ses extensions � ils sont ina
essibles
à l'extérieur de la lasse parente...
• ...mais es hamps existent dans les instanes de l'extension,
même s'ils sont ina
essibles dans l'extension elle-même.
• ...et les méthodes de la lasse parente héritées par l'extension
ontinuent à a
éder librement à es hamps (puisqu'elles
les �voient� depuis la lasse parente).
Programmation en Java 59
lass Point2D {
private int abs, ord; // abs et ord existeront mais seront masques
int getAbs() { // dans les heritiers
return abs;
} // les hamps abs et ord sont
int getOrd() { // visibles dans ette lasse
return ord;
}void set(int abs, int ord) {
this.abs = abs; this.ord = ord;
}
}
lass Point2DColore extends Point2D {
private int ol;
int getCol() {
return ol;
}void set(int abs, int ord, int ol) {
set(abs, ord); // invoation du set en (int,int) qui, depuis
this.ol = ol; // sa lasse, a
ede aux hamps masques
}
}
Programmation en Java 60
Point2DColore p = new Point2DColore();
p.set (10, 42, 255);
int i = p.getAbs(); // 10
int j = p.getOrd(); // 42
int = p.getCol(); // 255
• les expressions p.abs ou p.ord sont inompilables, même si
tout point oloré dispose bien de es deux hamps.
• les méthodes getAbs, getOrd sont héritées par Point2DColore. elles sont
implémentées dans Point2D, don a
èdent librement aux deux hamps
depuis leur lasse.
• la nouvelle méthode set invoque une implémentation de set héritée de
Point2D qui a
ède librement aux deux hamps depuis sa lasse.
Programmation en Java 61
• les onstruteurs d'une lasse ou ses méthodes peuvent également être
délarés private (plus rare).
• les règles sont les mêmes qu'ave les hamps (non hérités, a
essibles
indiretement via les implémentations héritées).
Programmation en Java 62
5.8. Extensions multiples et extensions d'extensions
• une même lasse peut avoir un nombre arbitraire d'extensions.
• toute extension de lasse peut elle-même être étendue.• restritions pour super.+ méthode et super(...) : une lasse
ne peut a
éder qu'à l'implémentation (héritée ou non) d'un
onstruteur ou d'une méthode de son anêtre immédiat :
on ne peut pas érire super.super...
Programmation en Java 63
lass Point2D {
private int abs, ord;
...
}
lass Point2DColore extends Point2D {
private int ol; // un hamp de plus...
...
}
lass Point2DColoreNomme extends Point2DColore {
private har nom; // enore un hamp de plus...
...
} // et..
// Point2D est parente de Point2DColore et de Point2DColoreNomme
// Point2DColore est parente de Point2DColoreNomme
Programmation en Java 64
• hiérarhie de lasses ≡ une lasse, et l'ensemble de ses
desendants (direts ou indirets)
• une lasse peut avoir plusieurs lasses anêtres (lasse parente, lasse
parente de ette lasse parente, et.) par onvention, les anêtres d'une
lasse inluent la lasse elle-même.
• une lasse prédé�nie est impliitement anêtre de toutes les autres :
la lasse Objet.
• un programme java se onçoit en général en onevant un ensemble de
hiérarhies de lasses (lasses génériques, spéialisations de es lasses,
spéialisations des spéialisations...)
Programmation en Java 65
PARTIE III - Classes Abstraites
Programmation en Java 66
6. Notion de lasse abstraite
• lasse abstraite ≡ lasse inomplète dont ertaines parties restent à érire :
� non instantiable (pas de new possible) mais elle peut ontenir
des hamps, des onstruteurs et des méthodes,
� elle peut mentionner des noms de méthodes non enore implémentées,
appelées méthodes abstraites,
� une lasse abstraite est uniquement destinée à être étendue en lasses
onrètes (instantiables), qui implémenteront les parties manquantes.
• objetif : toujours le même, érire une seule fois les éléments ommuns à
toutes les extensions, érire ensuite les spéialisations onrètes.
Programmation en Java 67
7. Délaration, extension de lasse abstraite - un exemple
• on souhaite délarer une lasse abstraite permettant de représenter
des formes géométriques, sans préision de leur nature exate (erle,
retangle, arré . . . ).
• toute forme est dé�nie relativement à un ertain point de référene
(deux hamps x et y ommuns à toutes les formes).
• toute forme doit pouvoir a�her sa desription (au moins les valeurs
des hamps x et y).
• toute forme o
upe une ertaine surfae... qui ne peut se aluler
qu'en onnaissant la nature exate de ette forme.
Programmation en Java 68
abstrat lass Forme { // "abstrat", i.e. abstraite
private int x, y; // hamps ommuns
Forme() {} // onstruteurs
Forme(int x, int y) {
this.x = x;
this.y = y;
}int getX() { return x; } // a
esseurs pour les
int getY() { return y; } // hamps ommuns
void setXY(int x, int y) {
this.x = x;
this.y = y;
}void affiher() {
System.out.println("base : " + x + "," + y);
}// methode abstraite : a implementer par les
// heritiers onrets de ette lasse abstraite.
abstrat double surfae(); // pas d'implementation.
}
Programmation en Java 69
lass Retangle extends Forme {
private int hauteur, largeur; // hamps supplementaires
Retangle() {} // onstruteurs
Retangle(int x, int y, int hauteur, int largeur) {
super(x,y); // init. des hamps de Forme
this.hauteur = hauteur; this.largeur = largeur;
}int getHauteur() { return hauteur; } // a
esseurs pour les
int getLargeur() { return largeur; } // hamps ajoutes
void setDimension(int hauteur, int largeur) {
this.hauteur = hauteur; this.largeur = largeur;
}void affiher() { // redefinition de l'affihage
super.affiher(); // appel de l'implementation de Forme,
System.out.println("hauteur : " + hauteur);
System.out.println("largeur : " + largeur);
}double surfae () { // implementation de la methode
return hauteur * largueur; // abstraite de Forme.
}
}
Programmation en Java 70
lass Cerle extends Forme {
private int rayon; // hamp supplementaire
Cerle() {} // onstruteurs
Cerle(int x, int y, int rayon) {
super(x,y);
this.rayon = rayon;
}int getRayon() { // a
esseurs pour le
return rayon; // hamp ajoute
}void setRayon(int rayon) {
this.rayon = rayon;
}void affiher() { // redefinition de l'affihage
super.affiher(); // appel de l'implementation de Forme,
System.out.println ("rayon : " + r);
}double surfae () { // implementation de la methode
return Math.PI * rayon * rayon; // abstraite de Forme.
}
}
Programmation en Java 71
• règles d'héritage, de onstrutions, d'a
essibilité des hamps, et. :
les mêmes que pour une extension de lasse onrète.
• toute lasse abstraite ou onrète peut être étendue en une lasse
onrète ou abstraite, toutes les extensions sont extensibles.
• une extension abstraite peut laisser abstraites une partie des méthodes
abstraite de sa lasse parente et en introduire de nouvelles.
• seule ontrainte sur les extensions :
toute extension onrète doit fournir une implémentation de haque
méthode enore abstraite dans sa lasse parente (héritée ou non).
Programmation en Java 72
PARTIE IV - Liaison dynamique
Programmation en Java 73
Programmation en Java 74
8. Conversions de référenes
8.1. Conversion asendante de référene
• Règle de délaration libre : on peut délarer des référenes vers
n'importe quelle lasse.
Forme f; // legal, meme si Forme est abstraite
• Regle de onversion asendante : on peut référener un objet
par toute référene vers l'une de ses lasses anêtres.
Forme f;
Cerle = new Cerle();
Retangle r = new Retangle();
f = ; // onversion "asendante" de
// en une referene vers Forme... legal.
f = r; // onversion "asendante" de r... legal.
Programmation en Java 75
8.2. Conversion desendante
• Règle de onversion desendante : on peut onvertir expliitement une
référene dans la diretion opposée, pourvu que la référene-ible soit vers
une lasse anêtre de elle de l'objet.
Forme f = new Cerle();
Cerle = (Cerle) f; // valide
// Retangle r = (Retangle) f;// erreur d'exeution !!
f = new Carre() // ou Carre est une extension de Retangle
Retangle r = (Retangle) f; // valide : Retangle est anetre de Carre.
• es onversions ne hangent pas les lasses des objets, mais simplement
le type des référenes qui servent à les manipuler.
Programmation en Java 76
8.3. Véri�ation de la validité d'une onversion
• on peut véri�er (à l'exéution seulement) la validité d'une
onversion desendante à l'aide de instaneof :
Forme f = Math.random() > .5 ? new Cerle() : new Carre ();
Retangle r = null;
if (f instane of Retangle) r = (Retangle) f;
• f instaneof Retangle vaut true si et seulement si Retangle est
anêtre de la lasse de f � i.e. si la onversion (Retangle) f est valide.
• instaneof ne permet pas de déterminer la lasse exate d'un objet, mais
simplement de véri�er si une lasse est anêtre de elle-i. en pratique,
son usage est réservé à la véri�ation de validité d'une onversion.
Programmation en Java 77
8.4. A
essibilité des noms suivant le type des référenes
• lorsqu'un objet est référené par une référene vers une ertaine lasse,
seuls les hamps et méthodes de ette lasse (non masqués, dans la lasse
ou hérités) sont a
essibles et invoables via ette référene.
Forme f = new Cerle();
f.affiher(); // legal : affiher est dans la lasse Forme
// f.setRayon(10); // erreur !! la lasse Forme ne ontient pas
// ette methode, definie dans Cerle.
Cerle = (Cerle) f; // desente vers Cerle
.setRayon(10); // legal.
Programmation en Java 78
9. Liaison dynamique
9.1. Règle de liaison dynamique � la règle entrale du langage
lorsqu'une méthode est invoquée sur une référene, l'implémentation
hoisie est toujours elle de la lasse de l'objet référené (érite dans
sa lasse, ou héritée), quel que soit le type de ette référene.
• exemple :
Cerle = new Cerle(); Forme f = ;
f.affiher(); // dans les deux as, l'implementation
.affiher(); // hoisie est elle de Cerle.
f = Math.random() > .5 ? new Cerle() : new Retangle ();
f.affiher(); // implementation hoisie a l'exeution !
affiher() sera lié (assoié) dynamiquement (à l'exéution) à une
ertaine implémentation, suivant la lasse de l'objet.
Programmation en Java 79
// exemple preedent, tres simplifie :
abstrat lass Forme {
abstrat void affiher();
}
lass Retangle extends Forme {
void affiher() { System.out.println("Retangle"); }
}
lass Cerle extends Forme {
void affiher() { System.out.println("Cerle");
}Retangle r = new Retangle();
Forme f = r;
f.affiher(); // affihe "Retangle", omme r.affiher()
Cerle = new Cerle();
f = ;
f.affiher(); // affihe "Cerle", omme .affiher()
Forme[℄ dessin = {new Retangle(), new Carre()};
for (int i = 0; i < 2; i++) dessin[i℄.affiher();
// affihe "Retangle" puis "Cerle"
Programmation en Java 80
// autre exemple : type de donnees abstrait
abstrat lass Pile {
abstrat int pop();
abstrat void push(int n);
abstrat boolean isEmpty();
}... // ailleurs : lasse(s) onrete(s) etendant Pile...
// implementation(s) par tableau, liste hainee, et.
... // et quelque part dans une autre lasse :
void m(Pile p) {
if (!p.isEmpty()) { // invoquera les methodes de la
int n = p.pop(); // lasse (onrete) de p.
// et.
} // la methode est dite "polymorphe" : elle a
epte des
} // objets de lasses differentes, en ne se servant que
// de leurs noms de methodes ommuns.
Programmation en Java 81
9.2. Règle de hoix d'implémentation des méthodes
• Si l'on invoque un nom de méthode sur des arguments de
types U1,. . . , Un, la méthode hoisie sera elle de signature
T1,. . . , Tn, où haque Ti est le plus prohe anêtre de Ui.
lass A {...}
lass B extends A {...}
lass C extends B {...}
lass D extends C {...}
// ... dans une lasse E : surharge du nom de methode m
void m(A a) {...}
void m(C ) {...}
// ... et ailleurs :
D d = new D(); C = d; B b = d; A a = d;
e.m(d); // methode invoquee : elle en (C)
e.m(); // methode invoquee : elle en (C)
e.m(b); // methode invoquee : elle en (A)
e.m(a); // methode invoquee : elle en (A)
Programmation en Java 82
PARTIE V - Interfaes
Programmation en Java 83
10. Notion d'interfae
• interfae ≡ similaire à une lasse abstraite, mais enore plus inomplète.
une simple liste de noms de méthodes.
interfae Deplaable {
Point2D getPosition();
void setPosition(Point2D p);
void alignerAve(Deplaable d);
}
• une lasse implémente une interfae lorsqu' elle implémente haune
de ses méthodes.
• une lasse ne peut être l'extension que d'une seule lasse, mais elle peut
implémenter plusieurs interfaes.
Programmation en Java 84
interfae Deplaable {
Point2D getPosition();
void setPosition(Point2D p);
void alignerAve(Deplaable d);
}
lass Segment implements Deplaable {
Point2D debut, fin;
// onstruteurs, et.
publi Point2D getPosition() {
return debut;
}publi void setPosition(Point2D p) {
debut.translater(p);
fin.translater(p);
}publi void alignerAve(Deplaable d) {
setPosition(d.getPosition());
}
}
Programmation en Java 85
interfae Deplaable {
Point2D getPosition();
void setPosition(Point2D p);
void alignerAve(Deplaable d);
}// ...
abstrat lass Forme implements Deplaable {
// hamps x, y, onstruteurs, et.
publi Point2D getPosition() {
return new Point2D(getX(), getY())
}publi void setPosition(Point2D p) {
setX(p.getX()); setY(p.getY());
}publi void alignerAve(Deplaable d) {
setPosition(d.getPosition());
}
}
lass Cerle extends Forme { ... } // implemente impliitement Deplaable par heritage.
Programmation en Java 86
• pas de lien de parenté entre Segment et les héritiers onrets de Forme...
mais "pont" réé entre toutes es lasses : une interfae ommune.
• alignerAve a
epte tout objet dont la lasse implémente Deplaable.
tous es objets sont référençables par des référenes de type Deplaable.
Deplaable d = new Cerle(); // onversion asendante
Deplaable e = new Segment(); // onversion asendante
d.alignerAve(e); // legal
e.alignerAve(d); // legal
Segment s = new Segment(); // onversion asendante
Cerle = new Retangle(); // de en referene vers
s.alignerAve(); // Deplaable. legal.
Programmation en Java 87
• une lasse peut implémenter plusieurs interfaes :
lass B extends C implements I, J, K {...}
• une lasse abstraite peut être marquée omme implémentant une interfae,
mais ne pas implémenter toutes ses méthodes.
• les interfaes sont extensibles, et même multi-extensibles
interfae I { ... }
interfae J { ... }
interfae K extends I, J { ... }
• on peut ajouter des hamps - impliitement final et stati.
Programmation en Java 88
Annexe - Compléments
Programmation en Java 89
11. Finalité de lasses, hamps, méthodes variables
• final ≡ plus modi�able, en plusieurs sens.
• final lass C {...} : la lasse C n'est plus extensible.
• lass C { final int x; ... }
le hamp x doit être initialisé dès la réation, et ne sera plus modi�able.
• lass C {... final int m() {...} }
le méthode m() ne pourra pas être rédé�nie dans les extensions de C.
• final permet de réer des objets non-mutables.
• variables en final ≡ onst de C.
Programmation en Java 90
12. Champs et méthodes statiques
• hamp statique ≡ hamp partagé par toutes les instanes d'une lasse.
• un seul exemplaire de e hamp en mémoire. reservé dès le lanement
du programme, et indépendamment de toute réation d'objet.
lass Point2D {
stati int nbreInstanesCrees = 0; // ompteur ommun a tous les points.
int abs, ord;
Point2D() { nbreInstanesCrees++; }
Point2D(int abs, int ord) {
this();
this.abs = abs;
this.ord = ord;
}
}
Programmation en Java 91
• a
ès à un hamp statique :
� via le nom de la lasse
� ou via une référene initialisée dont la lasse voit e hamp
// lanement du programme.
System.out.println(Point2D.nbreInstanesCrees); // affihe 0
Point2D p = new Point2D(); // premiere instane reee.
System.out.println(Point2D.nbreInstanesCrees); // affihe 1
// et.
Programmation en Java 92
• méthode statique ≡ une méthode qui n'a
ède qu'à des hamps statiques.
invoable indépendamment de tout objet.
lass Point2D {
stati int nbreInstanesCrees = 0; // ompteur ommun
int abs, ord; // a tous les points.
Point2D() { nbreInstanesCrees++; }
stati void affiherNbreInstanesCrees() {
System.out.println(nbreInstanesCrees);
}
}
• invoation via le nom de la lasse (ou une référene initialisée) :
Point2D.affiherNbreInstanesCrees();
Programmation en Java 93
12.1. Appliations des hamps et méthodes statiques
• �librairie� de fontions utilitaires (omme en C)
lass Divers {
stati final double Pi = 3.1415927;
stati int max(int x, int y) {
return x > y ? x : y;
}stati int min(int x, int y) {
return x < y ? x : y;
}private Divers() {} // unique onstruteur prive...
} // don lasse non instantiable,
// et non extensible !
Programmation en Java 94
• dé�nitions de onstantes, et même onstantes d'objets :
lass Couleur {
stati final
BLANC = new Couleur (255,255,255),
NOIR = new Couleur (0,0,0);
final int r, v, b; // hamps non mutables
Couleur() {
this (0,0,0);
}Couleur (int r, int v, int b) {
this.r = r;
this.v = v;
this.b = b;
}
}
Programmation en Java 95
• lasse singleton : une, et une seule instane.
lass Elvis {
private stati final THE_KING = new Elvis ();
private Elvis() {} // prive... pas d'autre new possible
// pas d'extension possible.
stati Elvis getInstane() {
return THE_KING;
}
}
Programmation en Java 96
• lasse à deux éléments et seulement deux :
lass Boolean {
private final boolean b;
private stati final // deux instanes, et pas plus
Boolean TRUE = new Boolean (true),
FALSE = new Boolean (false);
private Boolean (Boolean b) {
this.b = b;
}stati Boolean getInstane(boolean b) { //"usine statique"
return b ? TRUE : FALSE;
}
}
Programmation en Java 97