Aziz DAROUICHI
FST-UCA
Mail to : pr.azizdarouichi@gmail.com
1
Programmation Orientée Objet
(Java 13)
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
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
Chapitre 6: Classse abstraite & Interfaces
Classes abstraites
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();
}
3
Classes abstraites
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 !!!).
4
Classes abstraites
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.
5
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
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.
17
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
Que les types des traitements
(signatures des méthodes)
Vue utilisateur
Classe abstraite
Propriétés et méthodes concrètes
Certaines méthodes doivent être
codées par d’autres.
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
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 Cloneable
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...
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
Interface Serializable
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
public class E {
int a = 21;
static class I{
int b = 12;
}
}
public class E {
int a = 21;
class I{
int b = 12;
}
}
E e = new E();
E.I i = new E.I();
E e = new E();
E.I i = e.new I();
Classe interne static/Classe interne non static
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 :
A a ;
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){
A a ;
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.
96
Q & A
97
Références
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. …

Chap 6 : classes et interfaces

  • 1.
    Aziz DAROUICHI FST-UCA Mail to: pr.azizdarouichi@gmail.com 1 Programmation Orientée Objet (Java 13)
  • 2.
    2 Classes abstraites Utilité desclasses 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 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 Chapitre 6: Classse abstraite & Interfaces
  • 3.
    Classes abstraites Utilité : Définirdes 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(); } 3
  • 4.
    Classes abstraites 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 !!!). 4
  • 5.
    Classes abstraites Une classeabstraite 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. 5
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
    Utilité des classesabstraites 11
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
    Interfaces Toutes les méthodessont 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. 17
  • 18.
  • 19.
    Interfaces 19 Du point devue 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;
  • 20.
  • 21.
    Interfaces 21 Exemple 1: public interfaceA { default void uneMethodeDeA(){ // implémentation } }
  • 22.
    Utilisation des interfaces 22 EnJava, 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.
  • 23.
    Utilisation des interfaces 23 Exemples: publicclass Report implements Printable{…} public class Book implements Printable, Zoomable{…} public class Circle extends Shape implements Printable{…} public class Square extends Rectangle implements Printable, Zoomable{…}
  • 24.
  • 25.
  • 26.
    Utilisation des interfaces 26 Exemple Tousles 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 … } … }
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
    Utilisation des interfaces 31 Interfaceset 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) ..... }
  • 32.
    Interfaces 32 Interfaces et constantes Exemple2: 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 ; } }
  • 33.
    Utilisation des interfaces 33 Dérivationd’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 ; }
  • 34.
    Utilisation des interfaces 34 Conflitsde 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() }
  • 35.
    Utilisation des interfaces 35 Conflitsde 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 }
  • 36.
    Utilisation des interfaces 36 Conflitsde 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 ?
  • 37.
    Utilisation des interfaces 37 Conflitsde 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é.
  • 38.
    Utilisation des interfaces 38 Conflitsde 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.
  • 39.
    L’interface Cloneable 39 La classeObject 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.
  • 40.
    Utilisation des interfaces 40 L’interfaceCloneable 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();
  • 41.
    Utilisation des interfaces 41 L’interfaceCloneable 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); } }
  • 42.
    Utilisation des interfaces 42 L’interfaceCloneable Exemple Résulat: MyStudent SIR 21 MyStudent SIR 21
  • 43.
  • 44.
    Interface fonctionnelle 44 Exemple: public interfaceStringComparator { int compare(String s1, String s2); }
  • 45.
  • 46.
    Interface fonctionnelle 46 Annotation: @FunctionalInterface Exemple: @FunctionalInterface publicinterface StringComparator { int compare(String s1, String s2); }
  • 47.
    Interface fonctionnelle 47 Une interfacefonctionnelle 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 ”; }; }
  • 48.
  • 49.
    Interface et classedé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.
  • 50.
    Interface et classedé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 }
  • 51.
    Classe abstraite ouInterface? 51
  • 52.
    Classe abstraite ouInterface? 52 Interface Que les types des traitements (signatures des méthodes) Vue utilisateur Classe abstraite Propriétés et méthodes concrètes Certaines méthodes doivent être codées par d’autres. Vue développeur
  • 53.
  • 54.
  • 55.
    Conflits de noms 55 Exemple: Considéronsles 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.
  • 56.
  • 57.
    Conflits de noms 57 Notonsqu'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 } }
  • 58.
  • 59.
    Interface de marquage 59 InterfaceCloneable 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.
  • 60.
    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
  • 61.
    61 Plus de détailssur l'interface Cloneable voir le lien suivant: https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/Cloneable.html Interface Cloneable
  • 62.
    Interface de marquage 62 InterfaceSerializable 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.
  • 63.
    Interface Serializable 63 L'interface Serializableest 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...
  • 64.
    64 Plus de détailssur l'interface Serializable voir le lien suivant: https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/io/Serializable.html Interface Serializable
  • 65.
    Classes internes 65 Java permetde 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 }
  • 66.
    Classes internes 66 Exemple 1: classExterne{ 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{ ..... } ..... }
  • 67.
    Classes internes 67 Exemple 2: classExterne{ private Interne i1, i2 ; // les champs i1 et i2 de Externe sont des références // à des objets de type Interne class Interne{ ..... } ..... }
  • 68.
    Classes internes 68 Lien entreobjet 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.
  • 69.
    Classes internes 69 Lien entreobjet 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 } . . . }
  • 70.
    Classes internes 70 Lien entreobjet 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 } …} … }
  • 71.
    Classes internes 71 Lien entreobjet interne et objet externe Exemple 2/2: Externe e1 = new Externe(), e2 = new Externe(); e1.fe(); e2.fe();
  • 72.
  • 73.
  • 74.
    Classes internes 74 Déclaration etinstanciation 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 ..... } ..... }
  • 75.
    Classes internes 75 Déclaration etinstanciation 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
  • 76.
    Classes internes statiques 76 Javapermet 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 } }
  • 77.
    Classes internes statiques 77 Exemple:(suite) Depuisl’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.
  • 78.
    Classes internes 78 Classe internestatic Classe interne non static public class E { int a = 21; static class I{ int b = 12; } } public class E { int a = 21; class I{ int b = 12; } } E e = new E(); E.I i = new E.I(); E e = new E(); E.I i = e.new I(); Classe interne static/Classe interne non static
  • 79.
    Classes internes 79 Remarque: Lors dela 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
  • 80.
    Classes internes locales 80 Uneclasse 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.
  • 81.
    Classes internes locales 81 Parexemple, 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.
  • 82.
    Classes internes locales 82 Exemple: publicclass 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 } }
  • 83.
    Classes internes locales 83 Remarque: Lorsde 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
  • 84.
    Classes anonymes 84 Java permetde 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.
  • 85.
    Classes anonymes 85 Définition Il s’agitde 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.
  • 86.
    Classes anonymes 86 Dérivation desuper classe Syntaxe SuperClasse var = new SuperClasse( ){ // méthodes redéfinies };
  • 87.
    Classes anonymes 87 Dérivation desuper 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 } ;
  • 88.
    Classes anonymes 88 Dérivation desuper classe Exemple 2/2: Tout se passe comme si l’on avait procédé ainsi : A a ; 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.
  • 89.
    Classes anonymes 89 Programme complet classA{ public void affiche() { System.out.println ("Je suis un A") ; } } public class Anonym1{ public static void main (String[] args){ A a ; 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
  • 90.
    Classes anonymes 90 Implémentation d’interface Interfacevar = new Interface(){ // implémentation des // méthodes de l’interface Interface };
  • 91.
    Classes anonymes 91 Implémentation d’interface Exemple2 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
  • 92.
    Classes anonymes 92 Utilisation dela 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.
  • 93.
    Utilisation de laré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 } ) ;
  • 94.
    Classes anonymes 94 Les classesanonymes 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!
  • 95.
    Classes anonymes 95 Utilisation dela 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.
  • 96.
  • 97.
    97 Références 1. Programmer enJava, 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. …