Vous êtes sur la page 1sur 135

1

La programmation orientée objet (POO)

o Exemple Objets
Objets
Classe Classe partner
etudiant1 4566A3
naciri Voiture noire
Etudiant ahmed 1250 Kg
22 immatriculation
nom couleur 80 Km/h
prenom genie logiciel
poids
age vitesse
option clio
etudiant2 accélérer() 1232R4
assisterCours() rasdi freiner() bleue
validerModule() ali 950 Kg
23 70 Km/h
management

o On dit que l’objet etudiant1 est une instance de la classe Etudiant.


o Immatriculation, couleur et poids sont les attributs de la classe Voiture.
o accélérer() et freiner() sont deux méthodes de la classe Voiture.
2

La programmation orientée objet (POO)

 Les attributs
o Ils représentent les propriétés et les caractéristiques d’un objet.
o Couleur et poids sont des attributs des objets relatifs à Voiture.
o Les objets instances de la même classe doivent avoir les mêmes
attributs.
o les attributs sont définis par des variables.
o Chaque attribut a une valeur pour chaque objet.
• Pour l’objet clio instance de la classe voiture on a: couleur porte la
valeur bleue et poids porte la valeur 950 Kg.
• Pour l’objet partner instance de la classe voiture on a: couleur porte la
valeur noire et poids porte la valeur 1250 Kg.
3

La programmation orientée objet (POO)

 Les méthodes
o Une méthode est une fonction ou une transformation qui peut être
appliquée aux objets ou par les objets dans une classe.
o Définit le comportement d'un objet et ce qui doit se passer lorsque
cet objet est créé, et les différentes tâches que l'objet peut effectuer
pendant sa durée de vie.
o Un étudiant (instance de la classe Etudiant) peut assister au cours et
peut valider un module.
o Une voiture ( instance de la classe Voiture) peut accélérer et peut
freiner.
4

La programmation orientée objet (POO)

 Syntaxe du langage Java


Pour créer une classe on suit les étapes suivantes:
o Toutes les déclarations de classe commencent par le mot réservé
"class" suivi du nom de la classe. La définition complète de la
classe (le corps) se trouve entre accolades;
o On commence par déclarer les attributs sous forme de variables;
o Les attributs doivent être déclarés private. (principe
d’encapsulation dans la POO);
o On passe à l’implémentation des différentes méthodes;
o Les méthodes utilisées sont déclarées public.
5

La programmation orientée objet (POO)

 Objet et référence

Voiture clio = new Voiture();

o Ainsi on dit que le nouveau objet créé est référencé par clio.
6

La programmation orientée objet (POO)

 Affectation et comparaison d’objets


o Affectation d’objets:
2 4
a b
5 9

L’affectation suivante: a=b; recopie simplement dans a la référence


contenue dans b, ce qui nous conduit à la situation ci-contre

2 b 4
a
5 9
7

La programmation orientée objet (POO)

 Affectation et comparaison d’objets 119


o Comparaison d’objets:
Les opérateurs == et != s'appliquent théoriquement à des objets.
L'expression a == b est vraie uniquement si a et b font référence à
un seul et même objet, et non pas seulement si les valeurs des
champs de a et b sont les mêmes.
2 2
a a
5 b 5

2
b 5
a==b retourne true
a==b retourne false a!=b retourne false
a!=b retourne true
8

La programmation orientée objet (POO)

 Notion de clone d’un objet et Ramasse-miettes


9

La programmation orientée objet (POO)

 Initialisation de référence et référence nulle


10

La programmation orientée objet (POO)

 Test de la classe créée


o On crée une autre classe pour le test contenant la méthode main, où
on écrira les instructions qui vont être exécutées.
o On fait un exemple d’instanciation.
 Exemple:

Voiture clio = new Voiture(); //création d’un objet clio de type Voiture

o On fait appel à la méthode accélérer de la classe Voiture.


 Exemple:

clio.accélérer(); // appel de la méthode accélérer pour l’objet clio


11

La programmation orientée objet (POO)

 Mot clé Final et This


• Classe X {
//…………………..
Private final int n=3; // la valeur de n est définie et fixé à 3
}

• Classe X{
Public X()
{ n=3;} // initialisation tardive , tout les objets de type X auront la même valeur du champ n
Private final int n;
}
• Classe X{
Public X(int nn)
{n=nn;}// les instances de A peuvent avoir des valeurs différentes cette fois
Private final int n;
}
12

La programmation orientée objet (POO)

 Mot clé Final et This (autoréférence)


Public Point (int a, int b)
{x= a; // peut aussi s’écrire : this.x=a; optionnelle
y=b; // peut aussi s’écrire : this.y=b; optionnelle
}

Public Point (int x, int y)


{this.x=x;
this.y=y;
}
13

La programmation orientée objet (POO)

 Méthodes particulières
o Accesseurs et mutateurs (getters et setters)
D’après ce qu’on a vu, les attributs sont déclarés avec le mot clé private
(principe d’encapsulation). Donc les attributs ne sont pas accessibles depuis
toute autre classe, en particulier la classe de test.
Afin d’accéder à un attribut pour changer sa valeur (en écriture) ou pour
récupérer sa valeur (en lecture) on utilise:
• Accesseur (getter) pour récupérer la valeur de l’attribut vitesse d’un objet de type Voiture:
public int getVitesse(){
return this.vitesse;
} // le type de retour du getter est le même que celui de l’attribut ( dans ce cas c’est int )
• Mutateur (setter) pour changer la valeur de l’attribut vitesse d’un objet de type Voiture:
public void setVitesse(int vitesse){
this.vitesse = vitesse; /*this c’est pour dire que this.vitesse c’est l’attribut vitesse de
l’objet courant et non pas l’argument vitesse de la méthode setVitesse()*/
} // le setter ne retourne rien donc le type de retour d’un setter est toujours void
14

La programmation orientée objet (POO)

 Méthodes particulières
o Notion de Constructeur
Un constructeur est une méthode qui va se charger de créer un
objet et, le cas échéant, d'initialiser ses variables. Cette méthode a
pour rôle de réserver de l'allocation mémoire pour notre futur objet
et par la suite d’en réserver pour tous ses attributs.
Les instructions de cette méthode s’exécutent au moment de
l’instanciation du nouveau objet.
• Les constructeurs doivent avoir le même nom que la classe.
• Les constructeurs n’ont pas un type de retour.
• Les instructions qui y existent décrivent le comportement de l’objet
lors de la création.
• Une classe peut posséder plusieurs constructeurs !!
15

La programmation orientée objet (POO)

 Méthodes particulières
o Constructeur (Suite)
• Exemple 1:

Public Voiture() {
}
//exemple de constructeur qui ne contient pas d’instructions

• Exemple 2:

Public Voiture() {
this.couleur = "bleue";
this.vitesse=60;
}
//exemple de constructeur qui initialise la couleur et la vitesse d’un
// objet au moment de l’instanciation.
16

La programmation orientée objet (POO)

 Règles concernant les constructeurs:


 Il n’est pas possible d’appeler directement un constructeur :
Exp: a.Point(2,3); // Erreur

 Il existe une exception : au sein d’un constructeur, il est possible


d’appeler un autre de la même classe . Pour cela, on fait appel au mot
clé this utilisé comme nom de méthode.
Exp: class Point
{ public Point (int a, int b)
{x=a; y=b;}
Public point ()
{this (0,0); // cette instruction doit être la première !!
}
17

La programmation orientée objet (POO)

 La surcharge (ou la surdéfinition) de méthodes:


o En java, on peut avoir dans la même classe deux méthodes qui ont
le même nom, à condition qu’elle aient des paramètres différents
( type ou nombre de paramètres).

les mêmes paramètres, Donc ils ne peuvent


o int afficherMessage(Strnig a, int b, int c){…}

Ces deux méthodes ont le même nom et

pas exister dans la même classe !!


Type Nom de Paramètres
de retour la méthode

o int afficherMessage(Strnig a, int b, String c){}


o int afficherMessage(Strnig a, int b){}
o int afficherMessage(Strnig a, int b, int c){} 
o float afficherMessage(String a, int b, int c){} 
18

La programmation orientée objet (POO)

 La surcharge (ou la surdéfinition) de méthodes:


o Surcharge de constructeur
Ainsi dans la même classe Voiture on peut définir les constructeurs
suivants:
Public Voiture() {
this.couleur = "bleue";
this.vitesse=60;
} //tous les objets créés vont avoir couleur= "bleue" et vitesse = 60

Public Voiture(String couleur, int vitesse) {


this.couleur = couleur;
this.vitesse= vitesse;
} // ce constructeur permet de personnaliser la couleur et la vitesse au
// moment de l’instaniciation.
19

La programmation orientée objet (POO)

 La surcharge (ou la surdéfinition) de méthodes:


o Surcharge de constructeur (Suite)
L’appel des constructeurs se fait pendant la création du nouveau
objet.
Voiture clio = new Voiture(); //appel du premier constructeur, appelé
//constructeur par défaut. L’objet clio a
// donc une couleur bleue et une vitesse 60!!

Voiture clio = new Voiture("bleue",80); //appel du deuxième constructeur


//qui reçoit comme arguments
// la couleur et la vitesse qu’on
//veut attribuer au nouvel objet
// créé.
20

La programmation orientée objet (POO)

 Types de variables
o Variable d’instance
Ce sont les attributs non static d’une classe, ils ont des valeurs
propres à chaque objet.
• Exemple: couleur et poids dans la classe Voiture.
nom et prénom dans la classe Etudiant.
o Variable de classe
C’est une variable commune entre toutes les instances, elle a la
même valeur pour tous les objets.
Les variables de classe sont déclarées static.
• Exemple d’utilisation: calcul du nombre d’instanciations.
21

La programmation orientée objet (POO)

 Types de variables
o Variable de classe (suite)
Par exemple, si nous définissons :
class B
{ static int n ;
float y ;
}
B a1 = new B(), a2 = new B() ;

nous aboutissons à cette situation


22

La programmation orientée objet (POO)

 Types de variables
o Variable de classe (suite)
Exp:
Class Obj {public Obj (){
Nb++;}
Private static ont Nb=0;}
Public class Test {
Public static void main ()
{ Obj a= new Obj();}
}
 Une méthode de classe ne peut pas agir sur un champ
d’instance (erreur)
23

La programmation orientée objet (POO)

 Types de variables (Suite)


o Variable locale
C’est une variable déclarée au sein d’une méthode (pas seulement
initialisée mais déclarée aussi).
Les variables locales ne sont connues que dans le bloc de code où
elles sont définies.
• Exemple:

public void augumenterVitesse(){


int i=10; // i est une variable locale (déclarée et initialisée dans cette methode
this.vitesse+=i;
System.out.println(this.vitesse);
}
24

La programmation orientée objet (POO)

 Initialisation des variables


o Initialisation par défaut des attributs
Contrairement au variables locales, les variables d’instance et les
variables de classe sont initialisées par défaut.

Type du champs Valeur par défaut


boolean false
char caractère de code nul
entier (byte, short, int, long) 0
flottant (float, double) 0.
objet null
25

La programmation orientée objet (POO)

 Initialisation des variables


o Initialisation explicite
C’est le fait d’affecter une valeur à la variable déclarée.
Toutes les variables peuvent être initialisées explicitement.
• Exemple
Public class A{
private int n = 10; //initialisation explicite à la valeur 10
private int p; // initialisation par défaut à la valeur 0
private boolean m; // initialisation par défaut à la valeur false
public A() { … } // constructeur
}

o L’instruction suivante A a = new A(); entraine successivement:


1) l'initialisation (explicite) du champ n à la valeur figurant dans sa déclaration, soit 10;
2) l'initialisation par défaut des champs non initialisés explicitement soit p à 0 et m à false;
3) l'exécution des instructions du constructeur.
26

La programmation orientée objet (POO)

 Ce qu’il faut retenir !!


o Une classe permet de définir des objets. Ceux-ci ont des attributs
(variables d'instance et variables de classe) et des méthodes
(accesseurs, mutateurs et autres).
o Le ou les constructeurs d'une classe doivent porter le même nom
que la classe, et pas de type de retour.
o Il est recommandé de déclarer ses variables d'instance private.
o Dans une classe, on accède aux variables de celle-ci grâce au mot
clé this.
o Une variable de classe est une variable devant être déclarée static.
o Les méthodes n'utilisant que des variables de classes doivent elles
aussi être déclarées static.
27

La programmation orientée objet (POO)

 Ce qu’il faut retenir !!


o Un fichier peut contenir plusieurs classes, dont une seule qui peut
être déclarée public. Le nom du fichier portera donc le nom de sa
classe déclarée public.
o Un fichier contenant du code java possède l’extension .java.
o On peut utiliser des packages (paquetages) pour regrouper les
classes d’un projet.
o Un fichier .java doit indiquer le nom du package dont il fait partie.
o Une classe qui fait appel à une classe appartenant à un autre
package doit implémenter une importation.
o Dans un fichier .java on commence par l’indication du package,
puis on fais les importations s’ils existent.
28

La programmation orientée objet (POO)

 Exercice 1
o Construire une classe qui représente un point, Chaque instance (objet) de
cette classe appelée Point possède 2 attributs privés x et y qui représentent
les coordonnées du point. Les cordonnées peuvent être fixer pendant la
construction du point, sinon on peut les changer après à l’aide des getters
et des setters. Proposer une méthode changerCoordonnées(int x, int y) qui
change à la fois les attributs x et y d’un point.
o Construire une deuxième classe qui représente un cercle, chaque instance
de cette classe possède 2 attributs privés o et r qui représentent
successivement le centre (de type point) et le rayon du cercle. On définit
lors de la construction le rayon r du cercle, puis on définit un getter et un
setter pour les deux attributs.
o Dans la classe de test, construire (instancier) un objet o de type Point (en
fixant x et y pendant la construction) et un objet cercle de type Cercle.
Puis définir o comme le centre de cercle. Ensuite utiliser le getter de cercle
pour afficher les cordonnées de o.
29

Les tableaux

 Les tableaux en Java sont différents de ceux des


autres langages. Ce sont de véritables objets (dont
la classe hérite de Object) :
 les éléments d’un tableau sont des variables, de types primitifs
ou références,
 les tableaux sont créés par l’opérateur new,
 ils ont une variable d’instance length qui fournit la taille d’un
tableau.
 Cependant, Java a une syntaxe particulière pour
 la déclaration des tableaux
 leur initialisation
30

Les tableaux
 Déclaration d’une référence à un tableau de int :
int[ ] tab; // ou int tab[ ];
Allocation d’un tableau et liaison à la référence déclarée
précédemment :
tab = new int[4];
 Allocation par initialiseur :
int[ ] tab = {10, 20, 30, 40};
tab = new int[ ] {1, 2, 3};
Remarque :
Si un tableau n’est pas initialisé lors de son allocation, les
éléments seront automatiquement initialisés à une valeur
par défaut en fonction de leur type :
31

Les tableaux

 Parcours d'un tableau :


int[] tab = new int[5];
for (int i = 0; i < tab.length; i++)
tab[i] = i * i;
32

Les tableaux
Remarques :
• Un accès a un élément d'un tableau qui dépasse sa capacité, lève une exception
du type java.lang.arrayIndexOutOfBoundsException.

• Java 5 fournit un moyen plus simple pour parcourir un tableau.


for(int element : tab)
System.out.println(element );
toute modification de « element » n'aura aucun effet sur le
contenu du tableau
33

Les tableaux
 Passage de tableaux en paramètre

void afficheTab(int[] tab)


{
for(int element : tab)
System.out.println(element );
}
34

tableaux à deux dimensions


 Déclaration :
int t [ ][ ];
int [ ][ ] t;
int [ ] t[ ];
Ces trois déclarations sont équivalentes. t est une référence à un tableau,
dans lequel chaque élément est lui-même une référence à un tableau
d’entiers.
 Allocation :

Exemple :
t = new int [2][3];

t[0] désigne la référence au premier tableau de 3 entiers,


t[1] désigne la référence au second tableau de 3 entiers,
t[0][i-1] désigne le ième élément du premier tableau.
Tableaux à deux dimensions

 Allocation par initialiseur


int [ ][ ] t = { {1, 2}, {3, 4, 5} }; 1 2

t 3 4 5

 Réallocation avec initialiseur


t[0] = new int[ ]{1,2,3}; 1 2 3
t[1] = new int[ ]{4,5}; t 4 5
35
Tableaux à deux dimensions
 Exemple : Triangle de Pascal

Le triangle est définit par les équations suivantes :


Ci,j = 1 si j=1 ou j=i
Ci,j = Ci-1,j-1 + Ci-1,j si 1<j<i
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
… … … … … …
36
Tableaux à deux dimensions

Exemple : Triangle de Pascal

class TrianglePascal
{
public static void main(String[] args)
{
int[ ][ ] triangle = new int [5][ ];
for( int i = 0; i < triangle.length; i++)
{
triangle [i]= new int [i+1];
triangle[i][0] = 1;
triangle[i][i] = 1;
for( int j = 1; j < triangle[i].length - 1; j++)
triangle[i][j] = triangle[i-1][j-1]+ triangle[i-1][j];
}
}
37
Les Packages
Un package (ou paquetage) est un
regroupement de classes qui sont fortement
liées du point de vu fonctionnel (même
domaine, même fonctionnalité).
Les packages permettent d'organiser les
librairies de classes Java et d'éviter d'éventuels
conflits de noms.
Un package peut contenir des sous-packages.
Les classes de la librairie standard Java sont
organisées en packages :
 java.lang : rassemble les classes de base Java (Object,
System, String, Math, …)
 java.util : rassemble les classes utilitaires (Vector,
Calendar, Date, Random, Scanner, …)
 java.io : entrées/sorties
 …
38
Instruction package

 Pour créer une classe dans un package, on écrit:


package <nom-package>;
class <nom-classe> {…}
Exemple :
package graphics;
class Point{ … }
class Segment{ … }
 Pour définir un sous-package dans un package, il faut préciser tout le
chemin pour arriver à ce sous-package comme suit:
package <package>.<sous-package>;
class <nom-classe> {…}
Par convention, la première partie du nom de package est le nom de
domaine Internet du créateur de la classe, renversé.
Exemple :
package ma.emsi.graphics;
 Si aucun package n'est précisé, alors c'est le package par défaut
(correspondant au répertoire courant) qui est utilisé.
39
Les packages : leur « existence »
physique
 A chaque classe Java correspond un fichier
 A chaque package correspond un
répertoire
Exemple : Main.java
package ma.emsi.graphics;
class Point{ … }
class Segment{ … }
class Main{ … }
Correspond à l'arborescence suivante :
40
accès aux éléments d'un
package
 Pour utiliser une classe (ou interface) publique
depuis un package autre que celui où elle a été
définie il existe trois possibilités :
• en indiquant le nom complet de la classe.
• en important la classe,
• en important tout le package où est définie la classe
41
accès aux éléments d'un package par
leur nom complet
Le nom complet d'une classe (fully qualified
name) est nomDuPackage.nomDeLaClasse
 en conséquence deux classes peuvent avoir le même nom
dans des packages de noms différents.
les classes de la librairie standard JAVA sont
toujours accessibles au travers de leur nom
complet ("fully qualified name" )
exemples de "fully qualified names" de
classes :
 java.lang.String
 java.util.Vector
 java.awt.Rectangle
 ma.emsi.graphics.Point
42
instruction import
l'instruction import permet d'accéder aux classes avec
un nom abrégé,
les instructions import, si elles sont présentes doivent
l'être nécessairement après l'instruction package et
avant toute définition de classe (ou d'interface),
l'instruction import peut avoir deux formes :
 import nomDePackage.nomDeClasse , la classe nomDeClasse peut
ensuite être désignée par son simple nom.
Exemple :
import ma.emsi.graphics.Point;

new Point(...);
 import nomDePackage.* , toutes les classes du package
nomDePackage peuvent ensuite être désignée par leur simple nom.
Exemple :
import ma.emsi.graphics.*;

new Segment(...);
43
instruction import

l'instruction import java.lang.*; est implicite


dans tout programme JAVA, elle rend
directement accessible les classes de base
JAVA,
si deux packages importés contiennent des
classes de nom identique, il est nécessaire
d'utiliser un nom complet pour désigner
chacune de ces deux classes.
A partir de la version 5, on peut importer les
champs et méthodes statiques :
Exemple :
import static java.lang.Math.*;
...
System.out.print("sin(PI/2) = " + sin(PI/2) );
44
Les packages : compilation et exécution

// Point.java //Segment.java //Main.java


package ma.emsi.graphics; package ma.emsi.graphics; package
ma.emsi.graphics;
public class Point{ … } public class Segment{ … } public class Main{…}

Compiler :
 Se placer dans le répertoire racine des packages (src)
 Spécifier tout le chemin pour désigner la classe
 …\src> javac -d ../bin ma/emsi/graphics/*.java

 Exécuter :
 Se placer dans le répertoire racine des packages (bin)
 Spécifier la classe en utilisant un nom complet
 …\bin> java ma.emsi.graphics.Main
45
46

Héritage et polymorphisme

 Héritage
o L'héritage est un mécanisme qui permet à une classe d'hériter de
l'ensemble des comportements et des attributs d'une autre classe.
o Grâce à l'héritage, une classe peut disposer immédiatement de
toutes les fonctionnalités d'une classe existante. De ce fait, pour
créer la nouvelle classe, il suffit d'indiquer dans quelle mesure elle
diffère de la classe existante.
o Une classe qui hérite d'une autre classe est appelée sous-classe ou
classe dérivée, et la classe qui offre son héritage à une autre est
appelée super-classe, classe de base ou classe mère.
47

Héritage et polymorphisme

 Héritage
o On dit que les classes Chien et Oiseau héritent
de la classe Animal. Ceci dit qu’elle possèdent
les mêmes propriétés et comportements que
Animal. Ainsi:

• un oiseau et un chien possèdent les propriétés:


couleur, sexe et appétit;
• un oiseau et un chien peuvent dormir et manger;
• un chien peut marcher mais ne peut pas voler ;
• un oiseau peut voler mais ne peut pas marcher!
48

Héritage et polymorphisme

 Héritage
o Dans la pratique, cela signifie que si la super-
classe possède un comportement et des attributs
dont vous avez besoin, il ne sera pas nécessaire
de la redéfinir ou d'en copier le code pour
disposer du même comportement et des mêmes
attributs dans votre classe. Votre classe recevra,
en effet, automatiquement ces éléments de sa
super-classe.
49

Héritage et polymorphisme

 Héritage
o La partie supérieure de la hiérarchie de
classes est occupée par la classe Object; toutes
les classes héritent des attributs et du
comportement de cette super-classe. La classe
Object est la classe la plus générale de la
hiérarchie. Cette classe est implicite, elle existe
systématiquement. Elle définit le comportement
et les attributs dont héritent toutes les classes de
la bibliothèque de classes de Java.
o On dit que toutes les classes java héritent de
la classe Object.
o Conséquence: en java tout est objet !!
50

Héritage et polymorphisme

 Syntaxe
51

Héritage et polymorphisme

 Exercice 2
o Nous allons voir comment mettre en œuvre l'héritage en Java, à partir
d'un exemple simple de classe ne comportant pas encore de constructeur.
Supposez que nous disposions de la classe Point suivante:
public class Point {
private int x,y;
public void initialise (int x, int y) {this.x = x; this.y = y; }
public void deplace (int x, int y) {this.x += x; this.y += y; }
public void affiche(){
System.out.println("je suis en "+this.x+" "+this.y); }
}

o Imaginons que nous ayons besoin d'une classe PointCol, destinée à


manipuler des points colorés d'un plan. Une telle classe peut
manifestement disposer des mêmes fonctionnalités que la classe Point,
auxquelles on pourrait adjoindre, par exemple, une méthode nommée
colore, chargée de définir la couleur.
52

Héritage et polymorphisme

 Exercice 2 (Suite)
o Il s'avère bien qu’un point coloré n’est qu’un point ayant une
couleur, donc un point coloré possède toutes les propriétés d’un
point plus une autre propriété qui s’appelle couleur.
o Ainsi, construire une classe PointCol qui hérite de la classe Point,
en ajoutant à la classe PointCol l’attribut couleur, et la méthode
colorer pour attribuer une couleur aux points colorés.
53

Héritage et polymorphisme

 Appel des constructeurs


o Supposons que la classe Point possède le constructeur suivant:

public class Point {


public Point (int x, int y) { this.x = x; this.y = y; }
}

o Ce constructeur qui reçoit deux arguments sert à initialiser les


coordonnées x et y lors de l’instanciation d’un objet Point.
o Supposons qu’on veut implémenter un constructeur pour la classe
PointCol qui fait l’initialisation des coordonnées x et y ainsi que la
couleur.
54

Héritage et polymorphisme

 Appel des constructeurs (Suite)


o Une façon de mettre en œuvre l’initialisation des attributs de
PointCol est d’utiliser le constructeur de sa classe mère Point, du fait
qu’il est accessible (déclaré public) et qu’il contient les deux
premières instructions de l’initialisation des attributs x et y.
o Pour le faire on utilise le mot réservé super:

public class PointCol extends Point {


public PointCol (int x, int y, String couleur) {
super(x, y); //obligatoirement comme première instruction !!
this.couleur = couleur; }
}
55

Héritage et polymorphisme

 Appel des constructeurs (Suite)


o l’instruction « super(x,y); » fait un appel au constructeur de la
classe Point qui est la super-classe de PoinCol, qui initialise
les deux attributs x et y. Il reste donc à ajouter l’instruction
« this.couleur=couleur; » pour initialiser l’attribut couleur :p
56

Héritage et polymorphisme

 Instanciation des objets:


o Dans le cas général des classes simples, la création d'un objet
fait intervenir les phases suivantes:
• allocation de mémoire;
• initialisation par défaut des champs (aux valeurs "nulles" habituelles );
• initialisation explicite, s’il y a lieu, des champs (aux valeurs données
par le programmeur lors de la déclaration);
• exécution des instructions du constructeur.

o La généralisation à un objet d'une classe dérivée est assez


intuitive. Supposons que: public class B extends A { ... }
57

Héritage et polymorphisme

 Instanciation des objets (Suite):


o La création d'un objet de type B se déroule en 6 étapes.
• Allocation mémoire pour un objet de type B ; il s'agit bien de
l'intégralité de la mémoire nécessaire pour un tel objet, et pas
seulement pour les champs propres à B (c'est-à-dire non hérités de
A).
• Initialisation par défaut de tous les champs de B (aussi bien ceux
hérités de A, que ceux propres à B) aux valeurs "nulles" habituelles.
• Initialisation explicite, s'il y a lieu, des champs hérités de A,
éventuellement, exécution des blocs d'initialisation de A.
• Exécution du corps du constructeur de A.
• Initialisation explicite, s'il y a lieu, des champs propres à B ;
éventuellement, exécution des blocs d'initialisation de B.
• Exécution du corps du constructeur de B.
58

Héritage et polymorphisme

 Dérivations successives :
o Jusqu'ici, nous n'avons raisonné que sur deux classes à la fois et
nous parlions généralement de classe de base et de classe dérivée.
En fait, comme on peut s'y attendre :
• d'une même classe peuvent être dérivées plusieurs classes différentes;
• les notions de classe de base (classe mère) et de classe dérivée (classe
fille) sont relatives puisqu'une classe dérivée peut, à son tour, servir
de classe de base pour une autre.
o Autrement dit, on peut très bien rencontrer des situations telles
que celle représentée par l'arborescence suivante :
59

Héritage et polymorphisme

 Dérivations successives (Suite) :

o La classe VéhiculeTerrestre est en même temps classe dérivée de


Véhicule et classe de base pour Voiture et Camion.
60

Héritage et polymorphisme

 Héritage multiple:
o Contrairement au C++, Java ne gère pas les héritages multiples :
une classe dérivée (ou encore classe fille) ne peut hériter que d'une
seule classe mère !
o Vous n'aurez donc JAMAIS ce genre de classe :
61

Héritage et polymorphisme

 Redéfinition de méthodes:
o Soient Point et PointCol deux classes telles que:

o Et soient p un objet instance de la classe Point et pc un


deuxième objet instance de la classe dérivée PointCol.
62

Héritage et polymorphisme

 Redéfinition de méthodes (Suite):


o L'appel p.affiche() fournit tout naturellement les coordonnées de
l'objet p de type Point. L'appel pc.affiche() fournit également les
coordonnées de l'objet pc de type Pointcol, mais bien entendu, il
n'a aucune raison d'en fournir la couleur.
o Si on veut que pc.affiche() affiche aussi la couleur de l’objet pc,
java nous permet de redéfinir la méthode affiche dans la classe
PointCol.
o Cette possibilité existe en Java; elle se nomme redéfinition de
méthode. Elle permet à une classe dérivée de redéfinir une
méthode de sa classe de base, en proposant une nouvelle
définition. Encore faut-il respecter la signature de la méthode
(type des arguments), ainsi que le type de la valeur de retour.
63

Héritage et polymorphisme

 Redéfinition de méthodes (Suite):

o Ainsi l’instruction pc.affiche() va afficher les coordonnées x et y


du point coloré pc et aussi sa couleur.
64

Héritage et polymorphisme

 Redéfinition de méthodes (Suite):


o La redéfinition d'une méthode s'applique à une classe et à toutes
ses descendantes jusqu'à ce que éventuellement l'une d'entre elles
redéfinisse à nouveau la méthode.
o Considérons par exemple l'arborescence suivante, dans laquelle la
présence d'un astérisque (*) signale la définition ou la redéfinition
d'une méthode f :
65

Héritage et polymorphisme

 Surcharge (ou Surdéfinition) et héritage


o Jusqu'à maintenant, nous n'avions considéré la surdéfinition qu'au sein
d'une même classe. En Java, une classe dérivée peut surdéfinir une
méthode d'une classe de base (ou, plus généralement, d'une classe
ascendante). En voici un exemple :
66

Héritage et polymorphisme

 Contraintes portant sur la redéfinition


o Valeur de retour
• Lorsqu'on surdéfinit une méthode, on n'est pas obligé de respecter le
type de la valeur de retour. Cet exemple est légal :
67

Héritage et polymorphisme

 Contraintes portant sur la redéfinition


o Valeur de retour (Suite)
• En revanche, en cas de redéfinition, Java impose non seulement
l'identité des signatures, mais aussi celle du type de la valeur de retour
:

• Ici, on n'a pas affaire à une surdéfinition de f puisque la signature de la


méthode est la même dans A et dans B. Il devrait donc s'agir d'une
redéfinition, mais comme les types de retour sont différents, on aboutit
à une erreur de compilation !!
68

Héritage et polymorphisme

 Contraintes portant sur la redéfinition


o Les droits d’accès
• Exemple:

• Attention : La redéfinition d'une méthode ne doit pas diminuer les droits


d'accès à cette méthode.
69

Héritage et polymorphisme

 Le polymorphisme
o Le terme polymorphisme décrit la caractéristique d'un élément qui
peut prendre plusieurs formes, comme l'eau qui se trouve à l'état
solide, liquide ou gazeux.
o En programmation Objet, le polymorphisme signifie que la même
opération peut se comporter différemment sur différentes classes
de la hiérarchie.
• Exemple
Le traitement de la méthode affiche() diffère selon l’objet sur laquelle
elle est appliquée. Pour un objet de type Point elle affiche les valeurs
des attributs x et y, mais pour un objet de type PointCol elle affiche
les valeurs des attributs x et y ainsi que celle de l’attribut couleur !!
70

Héritage et polymorphisme

 Les bases du polymorphisme


o Considérons cette situation dans laquelle les classes Point et
PointCol sont censées disposer chacune d'une méthode affiche(),
ainsi que des constructeurs habituels (respectivement à deux et
trois arguments):

public class Point {


public Point (int x, int y) { … }
public void affiche( ) { … }
}

class PointCol extends Point {


public PointCol (int x, int y, String couleur) { … }
public void affiche( ) { … }
}
71

Héritage et polymorphisme

 Les bases du polymorphisme (Suite)


o Avec ces instructions:
Point p ;
p = new Point (2, 5) ;

On aboutit tout naturellement 2 x


P
à cette situation: (Point) 5 y
o Mais il se trouve que Java autorise ce genre d'affectation (p étant toujours
de type Point)
p = new PointCol (4, 8, "bleu" ) ; // p de type Point contient la référence
//à un objet de type PointCol
La situation correspondante est 4 x
P
la suivante : (Point) 8 y
bleu couleur
72

Héritage et polymorphisme

 Les bases du polymorphisme (Suite)


o D'une manière générale, Java permet d'affecter à une variable
objet non seulement la référence à un objet du type
correspondant, mais aussi une référence à un objet d'un type
dérivé.
o On peut dire qu'on est en présence d'une conversion implicite
(légale) d'une référence à un type classe T en une référence à un
type ascendant de T; on parle aussi de compatibilité par
affectation entre un type classe et un type ascendant.
73

Héritage et polymorphisme

 Les bases du polymorphisme (Suite)


o Considérons maintenant ces instructions :
Point p = new Point (3, 5) ;
p.affiche () ; //appelle la méthode affiche de la classe Point
p = new PoinCol (4, 8, "bleu" ) ;
p.affiche () ; //appelle la méthode affiche de la classe PointCol

o Dans la dernière instruction, la variable p est de type Point, alors que


l'objet référencé par p est de type PointCol. L'instruction p.affiche()
appelle alors la méthode affiche de la classe PointCol.
o Autrement dit, elle se fonde, non pas sur le type de la variable p, mais
bel et bien sur le type effectif de l'objet référencé par p au moment de
l'appel (ce type pouvant évoluer au fil de l'exécution).
74

Héritage et polymorphisme

 Les bases du polymorphisme (Suite)


o Considérons maintenant ces instructions :
Point p = new Point (3, 5) ;
p.affiche () ; //appelle la méthode affiche de la classe Point
p = new PoinCol (4, 8, "bleu" ) ;
p.affiche () ; //appelle la méthode affiche de la classe PointCol

 Ce choix d’une méthode au moment de l’exécution (et non plus de la


compilation) porte généralement le nom de ligature dynamique (ou encore
de liaison dynamique)
75

Héritage et polymorphisme

 Les bases du polymorphisme (Suite)

 En résumé, le polymorphisme en Java se traduit par :

 • la compatibilité par affectation entre un type classe et un type


ascendant,

 • la ligature dynamique des méthodes.


76

Héritage et polymorphisme

 Les conversions explicites de références


o Nous avons largement insisté sur la compatibilité qui existe entre
référence à un objet d'un type donné et référence à un objet d'un type
ascendant. Comme on peut s'y attendre, la compatibilité n'a pas lieu dans
le sens inverse.
o Considérons cet exemple, fondé sur nos classes Point et PointCol
habituelles:
class Point { ... }
class PointCol extends Point { ... }
...
PointCol pc ;
pc = new Point (2,5) ; //erreur de compilation

o Si l'affectation était légale, un simple appel tel que pc.setCouleur(..)


conduirait à attribuer une couleur à un objet de type Point, ce qui
poserait quelques problèmes à l'exécution.
77

Héritage et polymorphisme

 Les conversions explicites de références (Suite)


o Mais considérons cette situation :

Point p ;
PointCol pc1 = new PointCol(2,5,"bleu");
PointCol pc2 ;
...
p = pc1 ; //p contient la référence à un objet de type PointCol
...
pc2 = p ; //refusé en compilation

o L'affectation pc2 = p est encore une fois refusée. Cependant, nous


sommes certains que p contient bien ici la référence à un objet de type
Pointcol.
o En fait, nous pouvons forcer le compilateur à réaliser la conversion
correspondante comme suit:
pc2 =(PointCol) p ; //accepté en compilation
78

Héritage et polymorphisme

 Les conversions explicites de références (Suite)


o Toutefois, lors de l'exécution, Java s'assurera que p contient bien
une référence à un objet de type PointCol (ou dérivé) afin de ne
pas compromettre la bonne exécution du programme. Dans le cas
contraire, on obtiendra une exception ClassCastException qui, si
elle n'est pas traitée (comme on apprendra à le faire
ultérieurement), conduira à un arrêt de l'exécution.
o Ce genre de conversion explicite n'est à utiliser qu'en toute
connaissance de cause !!
79

Héritage et polymorphisme

 Le mot clé final: les constantes


o En Java, le mot clé final sert à désigner une constante.
o Le mot clé final signifie que vous affectez la variable (variable
locale ou champs de classe) une seule fois, et une fois pour toutes.
Par convention, les noms des constantes sont entièrement en
majuscules.
• Exemple

final double CONSTANTE_GRAVITE = 9.81

o On est sûr durant le programme que notre variable ne changera


pas de valeur !
80

Héritage et polymorphisme

 Le mot clé final: les méthodes


o Le mot clé final peut aussi s'appliquer à une méthode ou à une
classe, mais avec une signification totalement différente :
Une méthode déclarée final ne peut pas être redéfinie
dans une classe dérivée !!
o Le comportement d'une méthode finale est donc complètement
défini et il ne peut plus être remis en cause, sauf si la méthode
appelle elle-même une méthode qui n'est pas déclarée final.
o On est sur que notre méthode ne changera pas de comportement
• Exemple

public final void nomMéthode() {


...
}
81

Héritage et polymorphisme

 Le mot clé final: les classes


o Une classe déclarée final ne peut plus être dérivée !!
o Les autres classes ne peuvent pas en hériter, ce qui veut dire
que l’arborescence d’héritage s’arrête au niveau de la classe
déclarée final.
• Exemple

public final class NomClasse {


...
}
82

Héritage et polymorphisme

 Le mot clé final: les classes (Suite)


o Question:
Est-ce qu’on pourrait croire qu'une classe finale est
équivalente à une classe non finale dont toutes les méthodes
seraient finales ??
o Réponse: En fait, ce n'est pas vrai car :
• ne pouvant plus être dérivée, une classe finale ne pourra pas se voir
ajouter de nouvelles fonctionnalités;
• une classe non finale dont toutes les méthodes sont finales pourra
toujours être dérivée, donc se voir ajouter de nouvelles
fonctionnalités.
83

Héritage et polymorphisme

 Ce qu’il faut retenir !!


o Une classe hérite d'une autre classe par le biais du mot clé
extends.
o Une classe ne peut hériter que d'une seule et unique classe !
o Si aucun constructeur n'est défini dans une classe fille, la JVM en
créera un et appellera automatiquement le constructeur de la classe
mère.
o La classe fille hérite de toutes les propriétés et méthodes public et
de la classe mère, les éléments déclarés private ne sont pas
accessibles.
o Si une méthode d'une classe mère n'est pas redéfinie, à l'appel de
cette méthode par le biais d'un objet enfant, c'est la méthode de la
classe mère qui sera appelée !
Super-class Object

Toutes les classes Java ont comme premier


ancêtre la classe lang.lang.Object.
Cette classe possède certaines méthodes
utiles à savoir :
 La méthode « String toString() »
 La méthode « boolean equals(Object obj) »
84
Les classes de bases: La classe String

 Les chaînes de caractères sont représentées en Java par


les classes :
 String est utilisé pour représenter les chaînes de
caractères non modifiables.
 StringBuffer est utilisé pour les chaînes de caractères
modifiables.

 Toutes les chaînes de caractères Java mémorisent des


caractères de type char.
85
Les classes de bases: La classe String

 Création d’un objet de type String :


• public String ()
• public String (String original)
• public String (char[] value)
• …

Exemple :
String str1= new String("Java");
String str2 = "Java";
char[] data = {'J', 'a', 'v', 'a'};
String str3 = new String(data);
String str4 = new String(str1);
86
Les classes de bases: La classe String

 Concaténation :
 public String concat(String str)
 Les opérateurs « + » et « += »
Exemple :
String str1 = "C++";
String str2 = "Java";
String str3 = str1.concat(" & ").concat(str2);
String str4 = str1 + " & " + str2;
str1 += " & " + str2;
 Longueur d’une chaîne :
 int length()
Exemple :
String str = "Java";
System.out.print( str.length() );
87
Les classes de bases: La classe String

 Comparaisons lexicographiques :
• public int compareTo(String anotherString)
• public int compareToIgnoreCase(String str)
• public boolean startsWith(String prefix)
• public boolean endsWith(String suffix)
• public boolean equals(Object anObject)
• public boolean equalsIgnoreCase(String anotherString)
Exemple :
String str1 = "java";
String str2 = "Java";
if(str1.compareTo(str2) > 0) System.out.println(true);
System.out.println( str1.startsWith(str2) );
System.out.println( str1.endsWith(str2) );
System.out.println( str1.equals(str2) );
88
Les classes de bases: La classe
String
 Recherche la position de la première occurrence d’un
caractère ou d’une chaîne de caractères :
• public int indexOf(int ch)
• public int indexOf(int ch, int fromIndex)
• public int indexOf(String str)
• public int indexOf(String str, int fromIndex)

• public int lastIndexOf(int ch)


• public int lastIndexOf(int ch, int fromIndex)
• public int lastIndexOf(String str)
• public int lastIndexOf(String str, int fromIndex)

Exemple :
String texte = "une chaîne de caractères";
int index = texte.indexOf('e') ;
while (index != -1) {
System.out.println(" « e » en position " + index) ;
index = texte.indexOf("e", index + 1) ; }
89
Les classes de bases: La classe String

 Extraction d’un caractère ou d’une sous-chaîne :


 public char charAt(int index)
 public String substring(int beginIndex);
 public String substring(int beginIndex, int endIndex)

Exemple :
String msg = "Chaîne de caractères";
System.out.println(msg.charAt(0));
System.out.println(msg.substring(7));
System.out.println(msg.substring(0, 6));

 Modification d’une chaîne :


 public String replace(char oldChar, char newChar)
 public String toLowerCase()
 public String toUpperCase()
 public String trim()
90
Les classes de bases: La classe String

 Convertit d’un type de donnée en une chaîne :


• public static String valueOf(typeSimple x)

Exemple :
int i = 20;
boolean b=true;
String str1 = String.valueOf( i );
String str2 = String.valueOf( b );
91
Les classes de bases: Les classes
enveloppes
 Les classe enveloppes (Wrappers) sont des classes qui
encapsulent les données de type primitif, afin de pouvoir les
utiliser comme des objets ordinaires. Depuis Java 5, les
opérations de conversion d'un type primitif vers un objet d'une
classe enveloppe, et la conversion inverse sont devenues
automatique : boxing et unboxing. Les classes enveloppes
sont immuables.
Type primitif Classe enveloppe
boolean Boolean
char Character
byte Byte
short Short
int Integer
long Long
float Float
double Double
92
Les classes de bases: Les classes
enveloppes
 Les constructeurs :

 public ClasseEnveloppe (typeSimple valeur)


public Integer (int value)
public Double (double value)
… …
 public ClasseEnveloppe (String s) /* Sauf pour Character */
public Integer (String s)
public Double (String s)

 Les méthodes de conversion

 public typeSimple typeSimpleValue ( )


public int intValue()
public double doubleValue()

93
Les classes de bases: Les classes
enveloppes
• public static ClasseEnveloppe valueOf(String s)
public static Integer valueOf(String s)
public static Double valueOf(String s)

• public static ClasseEnveloppe valueOf(typeSimple x)
public static Integer valueOf(int valeur)
public static Double valueOf(double valeur)

• public static typeSimple parseTypeSimple(String s)
public static int parseInt(String s)
public static double parseDouble(String s)

94
Les classes de bases: Les classes
enveloppes
 Quelques méthodes utiles pour la classe Character :
public static boolean isLetter (char c)
public static boolean isDigit (char c)
public static boolean isLowerCase (char c)
public static boolean isUpperCase (char c)

 Les constantes :
• public static final typeSimple MIN_VALUE
• public static final typeSimple MAX_VALUE
95
Les classes de bases: Les classes
enveloppes
Exemple
Integer i1 = new Integer(10);
Integer i2 = 10; // boxing
Integer i3 = Integer.valueOf( 10 );

Integer i4 = i2 * i3;
Integer i5 = Integer.valueOf( i2.intValue() * i3.intValue() );

//Integer i6 = "10"; //Erreur


Integer i7 = Integer.valueOf( "10" );

String s = Integer.toString( 10 );
int i8 = Integer.valueOf( s ).intValue();
int i9 = Integer.parseInt( s );

int i10 = i1; //unboxing


int i11 = i1.intValue();

System.out.println( Integer.toBinaryString(15) );
96
Les classes de bases: Les classes
enveloppes
Exemple :

String str = "ref 120";

for(int i=0; i<str.length(); i++)


System.out.print( Character.toUpperCase( str.charAt(i) ) + " " );

System.out.println("\n" + str.toUpperCase() );
97
Les classes de bases: La classe
Scanner
 La classe Scanner a été introduite à partir de la version java
5. Elle simplifie la lecture de données sur l’entrée standard
(clavier).

 Pour utiliser la classe Scanner, il faut d’abord l’importer :


import java.util.Scanner;

 Ensuite il faut créer un objet de la classe Scanner de la


manière suivante :
Scanner stdin = new Scanner(System.in);
98
Les classes de bases: La classe
Scanner
 Pour lire les données sur l’entrée standard et les récupérer, la
variable stdin doit faire appel aux méthodes décrites ci-dessous
:
• public String next()
• public String nextLine()
• public typeSimple nextTypeSimple()

 Il peut être utile de vérifier le type d’une donnée avant de la lire


:
• public boolean hasNext()
• public boolean hasNextLine()
• public boolean hasNextTypeSimple()
99
Les classes de bases: La classe
Scanner
Exemple :
int i;
double d;
String str;
char c;

Scanner stdin = new Scanner(System.in);

System.out.print("Entrez un entier : ");


i = stdin.nextInt();

stdin.nextLine();
System.out.print("Entrez une chaine : ");
str = stdin.nextLine();

System.out.print("Entrez un caractère : ");


c = stdin.next().charAt(0);

stdin.nextLine();
System.out.print("Entrez un réel : ");
d = stdin.nextDouble();
100
101

Les classes abstraites et les interfaces

 Les classes abstraites


o Une classe abstraite est une classe qui ne permet pas
d'instancier des objets.
o Elle ne peut servir que de classe de base pour une dérivation,
donc une classe abstraite est là pour être héritée !!
• Exemple

public abstract class A {


...
}
102

Les classes abstraites et les interfaces

 Les méthodes abstraites


o Dans une classe abstraite, on peut trouver classiquement des méthodes
et des champs, dont héritera toute classe dérivée. Mais on peut aussi
trouver des méthodes dites abstraites, c'est-à dire dont on ne fournit
que la signature et le type de la valeur de retour.
• Exemple
public abstract class A {
public void f ( ) {…} // f est définie dans A
public abstract void g (int n); // g n’est pas définie dans A; on n’écrit que l’entête
// Attention, n’oubliez pas le point virgule !!
}
o Remarque: On peut déclarer une variable de type A, mais chaque
instanciation sera rejetée par le compilateur !!

A a ; // OK : a n'est qu'une référence sur un objet de type A ou dérivé


a = new A(...) ; // erreur : pas d'instanciation d'objets d'une classe abstraite
103

Les classes abstraites et les interfaces

 Les méthodes abstraites (Suite)


o En revanche, si on dérive de A une classe B qui définit la méthode
abstraite g :

public class B extends A {

public abstract void g (int n) { … } // ici on définit g !!


}

o On pourra alors instancier un objet de type B par new B(..) et même


affecter sa référence à une variable de type A :
• Exemple

A a = new B(...) ; // OK
104

Les classes abstraites et les interfaces

 Quelques règles
o Dès qu'une classe comporte une ou plusieurs méthodes abstraites, elle est
abstraite, et ce même si l'on n'indique pas le mot clé abstract devant sa
déclaration (ce qui reste quand même vivement conseillé). Ceci est
correct :
public class A {
public abstract void f ( ); // OK
}

Malgré tout, A est considérée comme abstraite et une expression telle que
new A(..) sera rejetée.
o Une méthode abstraite ne doit pas être final, ce qui est logique puisque sa
vocation est d'être redéfinie dans une classe dérivée.
o Une classe dérivée d'une classe abstraite n'est pas obligée de redéfinir
toutes les méthodes abstraites de sa classe de base.
105

Les classes abstraites et les interfaces

 Intérêt
o Le recours aux classes abstraites facilite largement la
Conception Orientée Objet. En effet, on peut placer dans une
classe abstraite toutes les fonctionnalités dont on souhaite
disposer pour toutes ses descendantes.
 soit sous forme d'une implémentation complète de méthodes (non
abstraites) et de champs (privés ou non) lorsqu'ils sont communs à
toutes ses descendantes;
 soit sous forme d'interface de méthodes abstraites dont on est alors sûr
qu'elles existeront dans toute classe dérivée instanciable.
106

Les classes abstraites et les interfaces

 Les interfaces
o Les interfaces sont des classes abstraites contenant uniquement des
définitions de constantes et des déclarations de méthodes, sans leur
définition (autrement dit, les méthodes indiquées dans les
interfaces ne comportent que le prototype sans le corps).
o La déclaration d'une interface se présente comme celle d'une
classe. On utilise simplement le mot clé interface à la place de
class :
interfcace I {
// liste des constantes
// liste des prototypes de méthodes (méthodes abstraites)
}

o Par essence, les méthodes d'une interface sont :


• abstraites (puisque nous ne fournissons pas de définition);
• publiques et non finales (puisqu'elles devront être redéfinies plus tard).
107

Les classes abstraites et les interfaces

 Les interfaces (Suite)


o Néanmoins, il n'est pas nécessaire de mentionner les mots clés
public et abstract (nous pouvons quand même le faire).
o Une interface peut être dotée des mêmes droits d'accès qu'une
classe (public ou droit de paquetage: default). Dans le cas où nous
désirons avoir une interface publique :
public interfcace Visualisation {
void affiche ( ); //déclaration sans définition
}

o Cette interface particulière possède une méthode. Certaines


interfaces possèdent plusieurs méthodes. Les interfaces ne
disposent jamais d'attributs (à part les constantes), et les méthodes
ne sont jamais implémentées directement dans l'interface. La
fourniture des attributs et des implémentations de méthodes sont
pris en charge par la ou les classes qui implémentent l'interface.
108

Les classes abstraites et les interfaces

 Implémentation d’une interface


o Une classe peut implémenter une interface, il s’agit de signer un
contrat de la part de la classe, qu’elle va implémenter toutes les
méthodes abstraites (prototypes) de cette interface.
o Pour qu'une classe implémente une interface et donc respecter le
contrat (ou la promesse) prévu par cette dernière, vous devez
exécuter deux étapes :
• déclarer que votre classe a l'intention d'implémenter l'interface donnée;
• fournir les définitions de toutes les méthodes de l'interface.

public class A implements Visualisation {


// A doit définir les méthodes prévues dans l’interface I
void affiche ( ) {
//définition de la méthode affiche
}
}
109

Les classes abstraites et les interfaces

 Implémentation d’une interface (Suite)


o Dans ce cas, la classe A:
• dispose des constantes définies dans l’interface Visualisation;
• est contrainte de définir toutes les méthodes prototypées dans
l'interface I; plus exactement, si la classe A ne définit pas toutes les
méthodes prototypées dans I, elle doit être déclarée abstraite et ne
pourra donc pas être instanciée.
o Les attributs (constantes) et les méthodes d'une interface sont
automatiquement publics; cela implique qu'une classe qui
implémente une interface devra déclarer publiques (avec le
modificateur public) les méthodes de l'interface qu'elle définit. Car
dans la redéfinition de méthodes, on ne doit pas diminuer les droits
d’accès.
110

Les classes abstraites et les interfaces

 Implémentation d’une interface (Suite)


o Si une classe A implémente une interface I, une sous-classe B de A
implémente aussi automatiquement I; une instance B pourra être
référencée par une variable de type I et bénéficiera, au moins par
héritage, des définitions des méthodes prototypées dans I.
• Exemple

public interface I { void méthode( ); }


public class A implements I {
public void méthode( ) { … }
}
public classe B extends A { … }
I i = new A ( ); // OK
I i = new B( ) ; // OK
i.méthode();
I i = new I ( ) ; // Erreur
111

Les classes abstraites et les interfaces

 Implémentation d’une interface (Suite)


o Une même classe peut implémenter plusieurs interfaces
• Exemple

public class A implements I1, I2 {


// A doit obligatoirement redéfinir les méthodes prévues dans I1 et I2
}

o Dans ce cas d'utilisation, les interfaces permettent de compenser,


en grande partie, l'absence d'héritage multiple !!
o Une interface peut bénéficier des avantages du polymorphisme.
o Les constantes d’une interface sont déclarés implicitement static et
final. Elles sont accessibles en dehors d'une classe implémentant
l'interface.
Les flux et les fichiers
 Un programme a souvent besoin de lire des données
depuis une source externe ou d’écrire des données vers
un destinataire externe.
 La source et la destination de ces échanges peuvent
être de natures multiples : fichier, socket réseau...
 De même, la nature des données échangées peut être
diverse : texte, images, son...

fichier entrée sortie


programme
lecture écriture
réseau
Les flux et les fichiers
 En java, le mécanisme de flux (‘stream’) permet de
représenter tous ces processus d’envoi/réception de
données.
 Java distingue :
 les flux d’entrée (lecture) et les flux de sortie (écriture),
 les flux binaires des flux texte. Dans le
 premier cas, l’information est transmise sans modification de la
mémoire au flux ou du flux à la mémoire. Dans le second cas, en
revanche, l’information subit une transformation, nommée formatage,
de manière que le flux reçoive ou transmette, en définitive, une suite de
caractères.
 Java propose des flux binaires permettant soit l’accès séquentiel, soit
l’accès direct.
Création séquentielle d’un fichier binaire
 La classe abstraite OutputStream sert de base à toutes
les classes relatives à des flux binaires de sortie.
 La classe FileOutputStream, dérivée de OutputStream,
permet de manipuler un flux binaire associé à un fichier
en écriture. L’un de ses constructeurs s’utilise ainsi :
 FileOutputStream f = new FileOutputStream
("entiers.dat") ;
 Cette opération associe l’objet f à un fichier de nom
entiers.dat. Si ce fichier n’existe pas, il est alors créé
(vide). S’il existe déjà, son ancien contenu est détruit. On
a donc affaire à une classique opération d’ouverture d’un
fichier en écriture.
Création séquentielle d’un fichier binaire
 il existe une classe DataOutputStream1 qui comporte
des méthodes plus évoluées et qui dispose (entre
autres) d’un constructeur recevant en argument un objet
de type FileOutputStream.
 Ainsi, avec :
 DataOutputStream sortie = new DataOutputStream (f) ;
 on crée un objet sortie qui, par l’intermédiaire de l’objet f,
se trouve associé au fichier entiers.dat.
 les deux instructions (création FileOutputStream et
DataOutputStream) peuvent être condensées en :
 DataOutputStream sortie = new DataOutputStream
( new FileOutputStream ("entiers.dat)) ;
Exemple
import java.io.* ;import java.Util.*;
public class Crsfic1
{ public static void main (String args[]) throws IOException
{
String nomfich ;
int n ; Scanner Clavier= new Scanner(System.in);
System.out.print ("donnez le nom du fichier a creer : ") ;
nomfich = Clavier.next() ;
DataOutputStream sortie = new DataOutputStream ( new FileOutputStream (nomfich)) ;
do { System.out.print ("donnez un entier : ") ;
n = Clavier.nextInt() ;
if (n != 0)
{ sortie. writeInt (n) ; }
}
while (n != 0) ;
sortie.close () ;
System.out.println ("*** fin creation fichier ***");
}
Exemple
 l’instruction : sortie.close () ; ferme le flux ; il ne sera
donc plus possible d’y écrire par la suite. En même
temps, elle assure la fermeture du fichier auquel le flux
est associé.
 la méthode writeInt (comme toutes les méthodes
d’écriture de DataOutputStrream) peut déclencher une
exception (explicite) du type IOException en cas d’erreur
d’écriture.
 Dans ces conditions celle-ci doit être soit traitée, soit
déclarée dans throws.
Liste séquentielle d’un fichier binaire

 la classe abstraite InputStream sert de base à toute


classe relative à des flux binaires d’entrée. La classe
FileInputStream, dérivée de InputStream, permet de
manipuler un flux binaire associé à un fichier en lecture.
 L’un de ses constructeurs s’utilise ainsi :
 FileInputStream f = new FileInputStream ("entiers.dat") ;
 Cette opération associe l’objet f à un fichier de nom
entiers.dat. Si ce fichier n’existe pas, une exception
FileNotFoundException (dérivée de IOException) est
déclenchée.
Liste séquentielle d’un fichier binaire

 il existe une classe DataInputStream qui possède des


méthodes plus évoluées et qui dispose (entre autres)
d’un constructeur recevant en argument un objet de type
FileInputStream. Ainsi, avec :
 DataInputStream entree = new DataInputStream (f) ;
 on crée un objet entree qui, par l’intermédiaire de l’objet
f, se trouve associé au fichier entiers.dat. Ici encore, les
deux instructions (création FileInputStream et création
DataInputStream) peuvent être condensées en :
 DataInputStream entree = new DataInputStream ( new
FileInputStream ("entiers.dat")) ;
Exemple
import javax.swing.* ; // pour showInputDialog
import java.io.* ;
public class Lecsfic1
{ public static void main (String args[]) throws IOException
{ String nomfich ;
int n = 0 ;
System.out.print ("donnez le nom du fichier a lister : ") ;
nomfich = Clavier.next() ;
DataInputStream entree = new DataInputStream ( new FileInputStream (nomfich)) ;
System.out.println ("valeurs lues dans le fichier " + nomfich + " :") ;
boolean eof = false ; // sera mis a true par exception EOFile
while (!eof)
{ try
{ n = entree.readInt () ;
}
catch (EOFException e)
{ eof = true ;
}
if (!eof) System.out.println (n) ;
}
entree.close () ;
System.out.println ("*** fin liste fichier ***");
}
}
Exemple
la fin de fichier apparaît en Java comme une exception. Cela nous
oblige donc à créer un bloc try réduit à une seule instruction de lecture,
et à détourner quelque peu la gestion d’exceptions de son but premier,
à savoir gérer des conditions exceptionnelles.
En outre, il est nécessaire d’initialiser artificiellement la variable n lors
de sa déclaration, afin d’éviter que l’instruction :
if (!eof) System.out.println (n) ;
soit rejetée par le compilateur sous prétexte que n peut ne pas être
initialisée (si une exception est déclenchée).
Accès direct à un fichier binaire
 Java permet de réaliser l’accès direct à un fichier binaire. À cet effet, il
dispose d’une classe spécifique RandomAccessFile qui dispose des
fonctionnalités des deux classes DataInput-Stream et DataOutputStream,
en particulier des méthodes readInt, readFloat, writeInt, writeFloat...

 Toutefois, comme la notion d’accès direct n’a de sens que pour un flux
connecté à un fichier, les constructeurs de la classe RandomAccesFile
requièrent tous un fichier. On y précise le nom, ainsi que le mode d’accès
; il s’agit d’une chaîne ayant l’une des deux valeurs "r" (lecture seule) ou
"rw" (lecture et écriture). Voici un exemple de construction d’un tel objet :
RandomAccesFile entree = new RandomAccessFile ("donnees.dat", "r") ;
Accès direct à un fichier binaire
 Par ailleurs, la classe RandomAccessFile dispose d’une méthode
spécifique seek permettant d’agir sur le "pointeur de fichier". Ce dernier
correspond au rang du prochain octet à lire ou à écrire (le premier octet
portant le numéro 0).

 Tant que l’on n’agit pas explicitement sur ce pointeur, il se trouve


incrémenté, après chaque opération, du nombre d’octets lus ou écrits.
Exemple
 Voici un programme qui permet d’afficher différents entiers de rang
donné d’un fichier binaire d’entiers du type de celui créé au paragraphe
1.2. On convient que l’utilisateur fournira un rang égal à 0 pour signaler
qu’il a achevé sa consultation :, après chaque opération, du nombre
d’octets lus ou écrits.
import java.io.* ;
public class Accdir
{ public static void main (String args[]) throws IOException
{ String nomfich ;
int n, num ;
RandomAccessFile entree ;
System.out.print ("donnez le nom du fichier a consulter : ") ;
nomfich = Clavier.next() ;
entree = new RandomAccessFile (nomfich, "r") ;
do
{ System.out.print ("Numero de l’entier recherche : ") ;
num = Clavier.nextInt() ;
if (num == 0) break ;
entree.seek (4*(num-1)) ;
Exemple
n = entree.readInt() ;
System.out.println (" valeur = " + n) ;
}
while (num != 0) ;
entree.close () ;
System.out.println ("*** fin consultation fichier ***");
}
}
Notez l’instruction :
entree.seek (4*(num-1)) ;
La formule 4*(num-1) se justifie par le fait que le premier octet est de rang 0 et que,
ici, nous avons convenu que, pour l’utilisateur, le premier entier du fichier porterait le
numéro 1.
Positionnement hors fichier
Lorsqu’on accède ainsi directement à l’information, le risque existe de se positionner
en dehors du fichier. En fait :
• S’il reçoit une valeur négative, seek lance une exception IOException. Si elle n’est
pas traitée, on obtient le message Negative seek offset.
• En revanche, aucune exception n’est déclenchée par seek si on lui fournit une
valeur supérieure à la taille actuelle du fichier. Mais on obtiendra une exception
EOFexception si on lance ensuite une opération de lecture. L’écriture, quant-à elle,
est toujours possible (si le fichier a été ouvert dans le mode "rw") puisque c’est
précisément comme cela qu’on peut créer un nouveau fichier.
 Dans ces conditions, lorsqu’on consulte un fichier existant en accès direct, le
mieux est de se protéger explicitement d’un mauvais positionnement :
• en déterminant la taille du fichier à l’aide de la méthode length de la classe
RandomAcces-File (attention, elle fournit un résultat de type long) ;
• en s’assurant que la valeur fournie à seek est bien non négative et inférieure à
cette taille.
Positionnement hors fichier
Voici comment nous pouvons modifier dans ce sens l’exemple précédent :
import java.io.* ;
public class Accdir1
{ public static void main (String args[]) throws IOException
{ String nomfich ; int n, num ;
RandomAccessFile entree ;
System.out.print ("donnez le nom du fichier a consulter : ") ;
nomfich = Clavier.lireString() ;
entree = new RandomAccessFile (nomfich, "r") ;
long taille = entree.length() ;
do
{ System.out.print ("Numero de l’entier recherche : ") ;
num = Clavier.lireInt() ; if (num == 0) break ;
Positionnement hors fichier
int rang = 4*(num-1) ;
if ( (rang>0) && (rang<taille))
{ entree.seek (rang) ;
n = entree.readInt() ;
System.out.println (" valeur = " + n) ;
}
else { System.out.println ("entier inexistant") ;
continue ;
}
}
while (num != 0) ;
entree.close () ;
System.out.println ("*** fin consultation fichier ***");
}
}
Les flux texte
 dans tous les environnements, on est habitué à manipuler des fichiers dits de
type texte (ou fichiers texte ou encore fichiers formatés).

 On peut dire que ce sont des fichiers que vous pouvez :


• créer ou consulter avec un éditeur de texte ou un traitement de texte employant le
mode texte ;
• lister par une commande de l’environnement, telle que type depuis une fenêtre
DOS sur PC, more ou pr sous Unix (ou Linux).
Création d’un fichier texte
 La classe abstraite Writer sert de base à toutes les classes relatives à un flux
texte de sortie. La classe FileWriter, dérivée de Writer, permet de manipuler un
flux texte associé à un fichier.
 L’un de ses constructeurs s’utilise ainsi :
FileWriter f = new FileWriter ("carres.txt") ;
 Cette opération associe l’objet f à un fichier de nom carres.txt2. S’il n’existe pas, il
est créé (vide). S’il existe, son ancien contenu est détruit. On a donc affaire à une
classique ouverture en écriture.
Création d’un fichier texte
 Les méthodes de la classe FileWriter permettent d’écrire des caractères, des
tableaux de caractères ou des chaînes. Dans certains cas, elles se révéleront
suffisantes. Mais, si l’on souhaite disposer de possibilités de formatage, on peut
recourir à la classe PrintWriter qui dispose d’un constructeur recevant en
argument un objet de type FileWriter. Ainsi, avec :
 PrintWriter sortie = new PrintWriter (f) ;
 on crée un objet sortie qui, par l’intermédiaire de l’objet f, se trouve associé au
fichier voulu.
 Bien entendu, les deux instructions peuvent être fusionnées en :
 PrintWriter sortie = new PrintWriter (new FileWriter ("carres.txt")) ;
 la classe PrintWriter dispose des méthodes print et println que nous allons
pouvoir utiliser exactement comme nous l’aurions fait pour afficher l’information
voulue à l’écran.
Exemple

 Soit un programme qui lit des nombres entiers au clavier et qui, pour chacun
d’entre eux, écrit une ligne d’un fichier texte contenant le nombre fourni
accompagné de son carré, sous la forme suivante :
12 a pour carrre 144
 On convient que l’utilisateur fournira la valeur 0 pour signaler qu’il n’a plus de
valeurs à entrer.
Exemple
 import java.io.* ;
 public class Crftxt1
 { public static void main (String args[]) throws IOException
 { String nomfich ;
 int n ;
 System.out.print ("Donnez le nom du fichier a creer : ") ;
 nomfich = Clavier.next() ;
 PrintWriter sortie = new PrintWriter (new FileWriter (nomfich)) ;
 do
 { System.out.print ("donnez un entier : ") ;
 n = Clavier.nextInt() ;
 if (n != 0)
 { sortie.println (n + " a pour carre " + n*n) ; } }
 while (n != 0) ; sortie.close () ;
 System.out.println ("*** fin creation fichier ***");}}
Accès aux lignes d’un fichier texte
 il n’existe pas de classe jouant le rôle symétrique de PrintWriter. Il faut se
contenter de la classe FileReader, symétrique de FileWriter. En la couplant avec
la classe Buffered-Reader qui dispose d’une méthode readLine, nous allons
pouvoir lire chacune des lignes de notre fichier
 avec FileReader seule, on ne pourrait accéder qu’à des caractères, et il nous
faudrait prendre en charge la gestion de la fin de ligne). Nous créons donc un
objet entree de la façon suivante :

 BufferedReader entree = new BufferedReader (new FileReader ("carres.txt")) ;


La méthode readLine de la classe BufferedReader fournit une référence à une
chaîne correspondant à une ligne du fichier.
 si aucun caractère n’est disponible (pas même une simple fin de ligne),
readLine fournit la valeur null.
Exemple
 import java.io.* ;
 public class Lecftxt1
 { public static void main (String args[]) throws IOException
 {
 String nomfich ;
 String ligne ;
 System.out.print ("Donnez le nom du fichier a lister : ") ;
 nomfich = Clavier.next() ;
 BufferedReader entree = new BufferedReader (new FileReader (nomfich)) ;
 do
 { ligne = entree.readLine() ;
 if (ligne != null) System.out.println (ligne) ;
 }
 while (ligne != null) ;
 entree.close () ;
 System.out.println ("*** fin liste fichier ***");}}

Vous aimerez peut-être aussi