Vous êtes sur la page 1sur 97

1

Programmation Orientée Objet


(Java 13)

Aziz DAROUICHI
FST-UCA
Mail to : pr.azizdarouichi@gmail.com
Chapitre 6: Classse abstraite & Interfaces
2

Classes abstraites
Utilité des classes abstraites
Interfaces
Utilisation des interfaces
Interface fonctionnelle
Héritage et Interface
Interface et classe dérivée
Classe abstraite ou Interface?
Gestion des exceptions
Conflits de noms
Interface de marquage
Classes interne, locale et anonyme
Q&A
Classes abstraites
3

Utilité :
Définir des concepts incomplets qui devront être implémentés
dans les sous-classes.
Factoriser le code.
public abstract class Forme{
protected double x, y;
public void deplacer(double dx, double dy) { // méthode concrète
x += dx;
y += dy;
}

public abstract double perimetre(); // méthode abstraite


public abstract double surface();
}
Classes abstraites
4

Classe abstraite : classe non instanciable, c'est à dire qu'elle


n'admet pas d'instances directes.
Impossible de faire new ClasseAbstraite(…);
Méthode abstraite : méthode n'admettant pas d'implémentation
au niveau de la classe dans laquelle elle est déclarée, on ne peut pas dire
comment la réaliser.
Une classe pour laquelle au moins une méthode abstraite est
déclarée, alors elle est une classe abstraite (l'inverse n'est pas vrai).
Les méthodes abstraites sont particulièrement utiles pour mettre
en œuvre le polymorphisme.
l'utilisation du nom d'une classe abstraite comme type pour une (des)
référence(s) est toujours possible (et souvent souhaitable !!!).
Classes abstraites
5

Une classe abstraite est une description d'objets destinée à être


héritée par des classes plus spécialisées.
Pour être utile, une classe abstraite doit admettre des classes
descendantes concrètes.
Toute classe concrète sous-classe d'une classe abstraite doit
“concrétiser” toutes les méthodes abstraites de cette dernière.
Une classe abstraite permet de regrouper certaines caractéristiques
communes à ses sous-classes et définit un comportement minimal
commun.
La factorisation optimale des propriétés communes à plusieurs
classes par généralisation nécessite le plus souvent l'utilisation de
classes abstraites.
Classes et méthodes abstraites
6
Classes abstraites
7

Métaphore
Classes abstraites
8
Classes abstraites
9

Règles
Classes abstraites
10

Règles
Utilité des classes abstraites
11
Classes abstraites
12

Exemple
Classes abstraites
13

Exemple
Classes abstraites
14

Exemple
Classes abstraites
15

Exemple
Classes abstraites
16

Exemple
Interfaces
17

Toutes les méthodes sont abstraites.


Possibilité d’héritage de plusieurs interfaces.
Les interfaces permettent de s’affranchir d’éventuelles contraintes
d’héritage.
Lorsqu’on examine une classe implémentant une ou plusieurs
interfaces, on est sûr que le code d’implémentation est dans le corps
de la classe. Excellente localisation du code (défaut de l’héritage
multiple).
Permet une grande évolutivité du modèle objet.
Interfaces
18
Interfaces
19

Du point de vue syntaxique, la définition d’une interface est proche


de celle d’une classe abstraite.
Il suffit de remplacer les mots-clés abstract class par le mot-clé
interface:
public interface Printable{
public void print();
}
Une fois l’interface déclarée, il est possible de déclarer des variables
de ce nouveau type:
Printable document;
Printable[] printSpool;
Interfaces
20
Interfaces
21

Exemple 1:
public interface A {
default void uneMethodeDeA(){
// implémentation
}
}
Utilisation des interfaces
22

En Java, une classe ne peut hériter que d’une et d’une seule classe
parente (héritage simple).
Une classe peut, par contre, implémenter une ou plusieurs
intefaces en utilisant la syntaxe suivante:
implements interface1, interface2, …
L’implémentation d’une ou plusieurs interfaces (implements) peut
être combinée avec l’heritage simple (extends).
La clause implements doit suivre la clause extends.
Utilisation des interfaces
23

Exemples:
public class Report implements Printable{…}
public class Book implements Printable, Zoomable{…}
public class Circle extends Shape implements Printable{…}
public class Square extends Rectangle
implements Printable, Zoomable{…}
Utilisation des interfaces
24
Utilisation des interfaces
25

Exemple
Utilisation des interfaces
26

Exemple
Tous les objets dont la classe implémente l’interface Comparable pourront
ensuite être triés.
public class Person implements Comparable{
private int age;

public int compareTo(Object p){
if (p instanceof Person ){
if (this.age<((Person)p).age) return -1;
if (this.age>((Person)p).age) return 1;
return 0;
} else …
}

}
Utilisation des interfaces
27

Exemple
Utilisation des interfaces
28

Exemple
Utilisation des interfaces
29

Exemple
Utilisation des interfaces
30

Exemple
Utilisation des interfaces
31

Interfaces et constantes
L’essentiel du concept d’interface réside dans les en-têtes de
méthodes qui y figurent.
Mais une interface peut aussi renfermer des constantes symboliques
qui seront alors accessibles à toutes les classes implémentant
l’interface :
interface I{
void f(int n) ;
void g() ;
static final int MAXI = 100 ;
}
class A implements I{
// doit définir f et g
// dans toutes les méthodes de A, on a accès au symbole MAXI :
// par exemple : if (i < MAXI) .....
}
Interfaces
32

Interfaces et constantes
Exemple 2:
public interface Constantes { // dans le fichier Constantes.java
public static final double G = 9.81;
}
public class ChampGravitationnel // dans le fichier ChampGravitationnel.java
implements Constantes {
private double vitesse ;
public double calculeVitesse(double temps) {
return G*temps ;
}
}
Utilisation des interfaces
33

Dérivation d’une interface


On peut définir une interface comme une généralisation d’une autre. On
utilise là encore le mot-clé extends, ce qui conduit à parler d’héritage ou
de dérivation, et ce bien qu’il ne s’agisse en fait que d’emboîter
simplement des déclarations :
interface I1{
void f(int n) ;
static final int MAXI = 100 ;}
interface I2 extends I1{
void g() ;
static final int MINI = 20 ;}
En fait, la définition de I2 est totalement équivalente à :
interface I2{
void f(int n) ;
void g() ;
static final int MAXI = 100 ;
static final int MINI = 20 ;
}
Utilisation des interfaces
34

Conflits de noms
Considérons les deux interfaces suivantes I1 et I2:
interface I1{
void f(int n) ;
void g() ;
}
interface I2{
void f(float x) ;
void g() ;
}
class A implements I1, I2{
// A doit définir deux méthodes f : void f(int) et void f(float),
// mais une seule méthode g : void g()
}
Utilisation des interfaces
35

Conflits de noms
Considérons ces deux interface A et B:
public interface A {
default void a() {
// implémentation
}
}
public interface B {
default void a() {
// implémentation
}
}
public class C implements A, B {
// !!! erreur de compilation !!!
// corps de la classe
}
Utilisation des interfaces
36

Conflits de noms
Construisons une instance de C et invoquons la méthode a().
La question qui se pose : quelle implémentation de la méthode a()
va-t-elle être invoquée ?
Celle de A ?
Celle de B ?
Utilisation des interfaces
37

Conflits de noms
Pour corriger cette erreur, il suffit tout simplement de lever
l'ambiguïté. Nous avons deux solutions pour ce faire.
Créer une implémentation concrète de la méthode a() dans la
classe C. Une implémentation concrète a toujours la priorité sur
une implémentation par défaut.
Décider qu'une des deux interfaces, par exemple A étend la seconde.
Dans ce cas, A devient plus spécifique que B, et l'on dit que c'est
l'implémentation la plus spécifique qui a la priorité.
Utilisation des interfaces
38

Conflits de noms
Remarque:
En cas de conflit l'implémentation concrète gagne contre
l'implémentation par défaut, et l'implémentation par défaut plus
spécifique gagne contre une moins spécifique.
L’interface Cloneable
39

La classe Object possède une méthode clone() protégée qui se


contente d’effectuer une copie superficielle de l’objet. L’idée des
concepteurs de Java est que cette méthode doit être redéfinie dans
toute classe clonable.
Il existe une interface très particulière Cloneable. Ce nom
s’emploie comme un nom d’interface dans une clause implements.
Mais, contrairement à ce qui se produirait avec une interface
usuelle, cette clause n’impose pas la redéfinition de la méthode
clone().
La déclaration:
class X implements Cloneable
mentionne que la classe X peut subir une copie profonde par appel de
la méthode clone(). Cette dernière peut être celle de Object ou une
méthode fournie par X.
Utilisation des interfaces
40

L’interface Cloneable
L’en-tête de la méthode clone() est :
protected Object clone()

Cela signifie que son utilisation nécessite toujours un cast de son


résultat dans le type effectif de l’objet soumis à copie.

La syntaxe pour invoquer cette méthode est la suivante:

Object copy = obj.clone();


ou
MaClasse copie = (MaClasse) obj.clone();
Utilisation des interfaces
41

L’interface Cloneable
Exemple
class Personne implements Cloneable{ // implémentation de l'interface Cloneable
private String nom; private String prenom; private int age;
public Personne(String unNom, String unPrenom, int unAge){
nom = unNom; prenom = unPrenom; age = unAge; }
public Object clone() throws CloneNotSupportedException{
return super.clone(); }

public static void main(String[] atgs){


Personne myStudent = new Personne("MyStudent","SIR", 21);
Personne myStudentClone = null;
try{
myStudentClone = (Personne) myStudent.clone(); // il faut réaliser un cast car la méthode clone renvoie un Object.
}catch(Exception e) {
System.out.println("Erreur");
}
System.out.println(myStudent.nom + " " + myStudent.prenom+" " + myStudent.age);
System.out.println(myStudentClone.nom + " " + myStudentClone.prenom+" " +
myStudentClone.age);
}
}
Utilisation des interfaces
42

L’interface Cloneable
Exemple
Résulat:
MyStudent SIR 21
MyStudent SIR 21
Interface fonctionnelle
43
Interface fonctionnelle
44

Exemple:
public interface StringComparator {
int compare(String s1, String s2);
}
Interface fonctionnelle
45

Annotation: @FunctionalInterface
Interface fonctionnelle
46

Annotation: @FunctionalInterface
Exemple:
@FunctionalInterface
public interface StringComparator {
int compare(String s1, String s2);
}
Interface fonctionnelle
47

Une interface fonctionnelle peut avoir des méthodes par défaut,


comme le montre l‘exemple ci-dessous :
Exemple:
@FunctionalInterface
public interface StringComparator {
int compare(String s1, String s2);
default String sayHello( ){
return “ Hello world ”;
};
}
Héritage et Interface
48
Interface et classe dérivée
49

La clause implements est une garantie qu’offre une classe


d’implémenter les fonctionnalités proposées dans une interface.
Elle est totalement indépendante de l’héritage; autrement dit, une
classe dérivée peut implémenter une interface ou plusieurs interfaces.
Interface et classe dérivée
50

Exemple:
interface I{
void f(int n) ;
void g() ;
}
class A {
.....
}
class B extends A implements I{
// les méthodes f et g doivent soit être déjà définies dans A,
// soit définies dans B
}
Classe abstraite ou Interface?
51
Classe abstraite ou Interface?
52

Interface Classe abstraite


Que les types des traitements Propriétés et méthodes concrètes
(signatures des méthodes) Certaines méthodes doivent être
codées par d’autres.

Vue utilisateur Vue développeur


Gestion des exceptions
53
Conflits de noms
54
Conflits de noms
55

Exemple:
Considérons les deux interfaces suivantes I1 et I2 :
interface I1{
void f(int n);
void g();
}
interface I2{
void f(float x);
int g();
}
class A implements I1, I2{
// pour satisfaire à I1 et I2, A devrait contenir à la fois une méthode
// void g() et une méthode int g(), ce qui n’est pas possible
// d’après les règles de redéfinition
}
Cette fois, une classe ne peut implémenter à la fois I1 et I2.
Conflits de noms
56
Conflits de noms
57

Notons qu'une implémentation peut appeler explicitement une


implémentation par défaut:
Exemple:
public interface A {
default void a() {
// implémentation
}
}
public class C implements A {
public void a() {
return A.super.a(); // appelle la méthode par défaut de A
}
}
Interface de marquage
58
Interface de marquage
59

Interface Cloneable
C’est une interface de marquage (ou balisage) : une classe qui
implémente l’interface Cloneable, indique à Object.clone() qu’il
est légal pour cet objet de faire une copie superficielle attribut par
attribut pour les instance de cette classe.
Une tentative de clonage pour des classes qui n’implémentent
pas Cloneable se traduit par la levée d’une exception:
CloneNotSupportedException.
Interface Cloneable
60

Par convention, les classes qui implémentent cette interface doit


redéfinir Object.clone() (qui est protected) avec une méthode
public.
Rappel:
La définition de clone() pour la classe Object est :
protected native Object clone() throws CloneNotSupportedException
Interface Cloneable
61

Plus de détails sur l'interface Cloneable voir le lien suivant:


https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/Cloneable.html
Interface de marquage
62

Interface Serializable
La sérialisation d'un objet est le processus de sauvegarde d'un
objet complet sur fichier, d'où il pourra être restauré à tout
moment.
Le processus inverse de la sauvegarde (restauration) est connu
sous le nom de désérialisation.
Interface Serializable
63

L'interface Serializable est une interface de marquage (ou balisage).


Cette interface ne comporte aucune méthode, sa seule fonction est
de marquer les classes qui pourront être "sérialisées", c'est-à-dire
dont les instances pourront être écrites dans des fichiers ou
transmises via un réseau.
Dans le jargon des développeurs Java, sérialiser un objet consiste à
le convertir en un tableau d'octets, que l'on peut ensuite écrire dans
un fichier, envoyer sur un réseau au travers d'une socket etc...
Interface Serializable
64

Plus de détails sur l'interface Serializable voir le lien suivant:


https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/io/Serializable.html
Classes internes
65

Java permet de définir une classe dite interne à l’intérieur d’une


autre classe.
La notion de classe interne correspond à cette situation:
class Englobante //définition d’une classe usuelle
{
… //méthodes et attributs de la classe Englobante
class Englobee{ //définition d’une classe interne à la classe Englobante
... //méthodes et attributs de la classe Englobee
}
... //autres méthodes et attributs de la classe Englobante
}
Classes internes
66

Exemple 1:
class Externe{
public void f() { // méthode de la classe Externe
Interne i = new Interne(); // création d’un objet de type Interne ;
// sa référence est ici locale à la méthode f
}
class Interne{
.....
}
.....
}
Classes internes
67

Exemple 2:
class Externe{
private Interne i1, i2 ; // les champs i1 et i2 de Externe sont des références
// à des objets de type Interne
class Interne{
.....
}
.....
}
Classes internes
68

Lien entre objet interne et objet externe


Une classe interne peut avoir toujours accès aux méthodes et
attributs (même privés) de la classe englobante/externe.
Une classe englobante/externe peut avoir toujours accès aux
méthodes et attributs (même privés) d’une classe interne.
Un objet d’une classe interne est toujours associé, au moment de
son instanciation, à un objet d’une classe externe.
Classes internes
69

Lien entre objet interne et objet externe


Exemple 1
class Externe {
int e;
class Interne{
...
Externe.this.e = 18; // ici, on a accès au champ e de l’objet de classe Externe associé à l’objet
//courant de classe Interne

}
...
}
Classes internes
70

Lien entre objet interne et objet externe


Exemple 1/2:
class Externe{
private int ne ; // champ privé de Externe
private Interne i1, i2 ; // les champs i1 et i2 de Externe sont des références à des objets de type Interne
public void fe(){
Interne i = new Interne() ; // création d’un objet de type Interne, associé à l’objet de classe Externe
} // lui ayant donné naissance (celui qui aura appelé la méthode fe())
public void g (){
..... // ici, on peut accéder non seulement à i1 et i2, mais aussi à i1.ni ou i2.ni
}
class Interne{
private int ni ;
public void fi(){
..... // ici, on a accès au champ ne de l’objet de classe Externe associé à l’objet courant de classe Interne
}
…}

}
Classes internes
71

Lien entre objet interne et objet externe


Exemple 2/2:
Externe e1 = new Externe(), e2 = new Externe();
e1.fe();
e2.fe();
Classes internes
72

Exemple pratique (1/2):


Classes internes
73

Exemple pratique (2/2):


Résultat:
Classes internes
74

Déclaration et instanciation d’un objet d’une classe interne


Il faut toujours rattacher un objet d’une classe interne à un objet de
sa classe englobante, moyennant l’utilisation d’une syntaxe
particulière de new.

public class E { // classe englobante de I


.....
public class I { // classe interne à E
.....
}
.....
}
Classes internes
75

Déclaration et instanciation d’un objet d’une classe interne


A l’extérieur de E, on peut déclarer une référence à un objet de
type I:
E.I i; // référence à un objet de type I (interne à E)
La création d’un objet de type I ne peut se faire qu’en le rattachant
à un objet de sa classe englobante.
Par exemple, si l’on dispose d’un objet e créé ainsi:
E e = new E() ;
On pourra affecter à i la référence à un objet de type I, rattaché à e,
en utilisant new comme suit :
i = e.new I(); // création d’un objet de type I, rattaché à l’objet e
// et affectation de sa référence à i
Classes internes statiques
76

Java permet de créer des classes internes "autonomes" en employant


l’attribut static.
Exemple:
public class E { // classe englobante
.....
public static class I { // définition (englobée dans celle de E)
..... // d’une classe interne autonome
}
}
Classes internes statiques
77

Exemple:(suite)
Depuis l’extérieur de classe E, on peut instancier un objet de classe
I de cette façon:
E.I i = new E.I();
L’objet i n’est associé à aucun objet de type E.
La classe I n’a plus accès aux membres de E, sauf s’il s’agit de
membres statiques.
Classes internes
78

Classe interne static/Classe interne non static

Classe interne static Classe interne non static


public class E { public class E {
int a = 21; int a = 21;
static class I{ class I{
int b = 12; int b = 12;
} }
} }

E e = new E(); E e = new E();


E.I i = new E.I(); E.I i = e.new I();
Classes internes
79

Remarque:
Lors de la compilation, le compilateur génère un fichier constitué
du nom de la classe englobante puis un ‘$’, puis le nom de la
classe interne, puis “.class”.
Par exemple, pour l’exemple précédent:
Génère E$I.class
Classes internes locales
80

Une classe interne définie dans un bloc est une classe interne dont
la portée est limitée au bloc : c’est une classe interne locale.
Une classe locale ne peut pas être static.
Une classe locale peut accéder aux attributs de la classe englobante
ainsi qu'aux paramètres et variable locales de la méthode où elle est
définie, à condition que ceux-ci soit spécifiés final.
Classes internes locales
81

Par exemple, la définition d’une classe interne I dans une


méthode f() d’une classe E.
L’instanciation d’objets de type I ne peut se faire que dans f.
Un objet de type I a alors accès aux variables locales finales de f.
Classes internes locales
82

Exemple:
public class E{
.....
void f(){
final int n=5 ;
double x ;
class I { // classe interne à E, locale à f
..... // ici, on a accès à n, pas à x
}
I i = new I() ; // classique
}
}
Classes internes locales
83

Remarque:
Lors de la compilation, le compilateur génère un fichier constitué
du nom de la classe englobante puis un ‘$’, puis un nombre,
puis le nom de la classe interne, puis “.class”
Par exemple, pour l’exemple précédent:
Génère E$1I.class
Classes anonymes
84

Java permet de définir ponctuellement une classe, sans lui donner


de nom.
Il permet de déclarer une classe et de créer un objet de celle-ci en
une expression.
La classe anonyme est un sous-type d'une interface ou d'une
classe abstraite ou concrète.
Classes anonymes
85

Définition
Il s’agit de classes dérivées ou implémentant une interface. La
syntaxe de définition d’une classe anonyme ne s’applique que dans
deux cas :
classe anonyme dérivée d’une autre,
classe anonyme implémentant une interface.
Classes anonymes
86

Dérivation de super classe


Syntaxe
SuperClasse var = new SuperClasse( ){
// méthodes redéfinies
};
Classes anonymes
87

Dérivation de super classe


Exemple 1/2:
Supposons que l’on dispose d’une classe A. Il est possible de créer un
objet d’une classe dérivée de A, en utilisant une syntaxe de cette
forme :
A a;
a = new A() {
// champs et méthodes qu’on introduit dans
// la classe anonyme dérivée de A
};
Classes anonymes
88

Dérivation de super classe


Exemple 2/2:
Tout se passe comme si l’on avait procédé ainsi :
Aa;
class A1 extends A {
// champs et méthodes spécifiques à A1
};
.....
a = new A1();
Cependant, dans ce dernier cas, il serait possible de définir des
références de type A1, ce qui n’est pas possible dans le premier cas.
Classes anonymes
89

Programme complet
class A{
public void affiche() {
System.out.println ("Je suis un A") ;
}
}
public class Anonym1{
public static void main (String[] args){
Aa;
a = new A() {
public void affiche (){
System.out.println ("Je suis un anonyme dérivé de A") ;
}
};
a.affiche() ;
}
}
Résultat: Je suis un anonyme dérivé de A
Classes anonymes
90

Implémentation d’interface

Interface var = new Interface(){


// implémentation des
// méthodes de l’interface Interface
};
Classes anonymes
91

Implémentation d’interface
Exemple 2
interface Affichable{
public void affiche() ;
}
public class Anonym2{
public static void main (String[] args){
Affichable a ;
a = new Affichable(){
public void affiche (){
System.out.println ("Je suis un anonyme implémentant Affichable") ;}
};
a.affiche() ;
}
}
Résultat: Je suis un anonyme implémentant Affichable
Classes anonymes
92

Utilisation de la référence à une classe anonyme


Dans les précédents exemples, la référence de la classe anonyme
était conservée dans une variable (d’un type de base ou d’un type
interface).
On peut aussi la transmettre en argument d’une méthode ou en
valeur de retour.
Utilisation de la référence à une classe anonyme
93

Exemple:
interface I{
.....
}
public class Util{
public static f(I i) {
.....
}
}
.....
f(new I() {
// implémentation des méthodes de I
});
Classes anonymes
94

Les classes anonymes possèdent des restrictions :


elles ne peuvent pas être déclarées abstract;
elles ne peuvent pas non plus être déclarées static;
elles ne peuvent pas définir de constructeur;
elles sont automatiquement déclarées final: l'héritage est donc
impossible!
Classes anonymes
95

Utilisation de la référence à une classe anonyme


Remarque:
L’utilisation des classes anonymes conduit généralement à des
codes peu lisibles.
On la réservera à des cas très particuliers où la définition de la
classe anonyme reste brève.
Q&A
96
Références
97

1. Programmer en Java, Claude Delannoy, Eyrolles, 2017


2. Programmation orientée objet avec Java, Jacques Bapst, École d’Ingénieurs et
d’Architectes de Fribourg.
3. http://blog.paumard.org/cours/java/
4. http://www.tutorialspoint.com/java/
5. https://docs.oracle.com/en/java/javase/13/index.html
6. …

Vous aimerez peut-être aussi