Cours Java1
Cours Java1
et Polymorphisme
Philippe Genoud
dernière mise à jour : 19/12/2017
©
© Philippe
Philippe GENOUD
GENOUD UGA
UJF Décembre 2017
2009 1
Surclassement
La réutilisation du code est un aspect important de l'héritage, mais ce n'est
peut être pas le plus important
Le deuxième point fondamental est la relation qui relie une classe à sa super-
classe :
Etudiant
Un EtudiantSportif est un Etudiant
à une référence déclarée de type A il est possible d'affecter une valeur qui
est une référence vers un objet de type B (surclassement ou upcasting)
Etudiant Etudiant e; A
e = new EtudiantSportif(...);
B C
EtudiantSportif D E
F
C c;
c = new D();
plus généralement à une référence d'un type donné, il est possible c = new E();
d'affecter une valeur qui correspond à une référence vers un objet c = new F();
dont le type effectif est n'importe quelle sous-classe directe ou c = new A();
indirecte du type de la référence c = new B();
© Philippe GENOUD UGA Décembre 2017 3
Surclassement
Lorsqu'un objet est "sur-classé" il est vu par le compilateur comme un objet du type
de la référence utilisée pour le désigner
Ses fonctionnalités sont alors restreintes à celles proposées par la classe du type
de la référence
Etudiant
EtudiantSportif es; String nom;
String prénom;
es = new EtudiantSportif("DUPONT","Jean", int age;
25,..,"Badminton",..); …
public Etudiant(String n, String p, int a ...)
es public void affiche()
Etudiant e;
e = es; // upcasting public int nbInscriptions()
...
e
[Link]();
[Link](); isa
DUPONT EtudiantSportif
[Link]();
[Link](); Jean
String sportPratiqué;
25 …
[Link](); ...
public EtudiantSportif (String n, String p,
[Link](); Badminton int a, …, String s, ...)
... public void affiche()
Le compilateur refuse ce message: public double bonusSportif()
pas de méthode bonusSportif ...
définie dans la classe Etudiant
© Philippe GENOUD UGA Décembre 2017 4
Lien dynamique
Résolution des messages
Etudiant
Que va donner [Link]() ? public void affiche() {
[Link](
"Nom : "+nom+"\n"
"Prénom : "+prénom+"\n"
Etudiant e = new EtudiantSportif( "Age : "+age+ ...);
"DUPONT","Jean",25,.., }
"Badminton",..); ?
[Link]();
e
isa ? EtudiantSportif
DUPONT
Jean public void affiche() {
[Link]();
25 [Link](
... "Sport" : "+sport+"\n"
+ ...);
Badminton }
...
isa ? EtudiantSportif
DUPONT
Nom : DUPONT public void affiche() {
Jean
Prénom : Jean [Link]();
25 Age : 25 [Link](
... … "Sport" : "+sport+"\n"
+ ...);
Badminton Sport : Badminton
}
...
la méthode définie pour le type réel de l’objet recevant le message est appelée
(et non pas celle définie pour son type déclaré).
garantir dès la compilation que les messages pourront être résolus au moment de
l’exécution robustesse du code
public class A {
A obj = new B();
A obj;
public void m1() { Type obj.m1();
for (int i = 0; i < 10; i++) {
[Link]("m1 de A"); déclaré obj hasard = [Link]()
} obj.m2();
} if ( hasard < 0.5)
obj = newcannot
[Link]: A(); resolve symbol
public class B extends A { else : method m2 ()
symbol
public void m1() {
[Link]("m1 de B"); location:
obj = class A
new B();
} obj.m2();
public void m2() { ^
[Link]("m2 de B"); obj.m1();
1 error
} }
}
vérification statique: garantit dès la compilation que les messages pourront être résolus
au moment de l’exécution
méthodeX()
ClasseB ClasseC
méthodeX()
surcharge
ClasseA [Link]("param typeA");
}
Pour que le transtypage soit valide, il faut qu’à l’exécution le type effectif de
obj soit « compatible » avec le type ClasseA
Compatible : la même classe ou n’importe quelle sous classe de ClasseA
(obj instanceof ClasseA)
Si la promesse n’est pas tenue une erreur d’exécution se produit.
[Link]: ClasseX
at [Link]([Link])
[Link](p1) -->
--> false
true
compilation exécution
[Link](); La classe C hérite d'une méthode ma méthode ma définie dans E
Incompatible types
B b = c; Un C n'est pas un B
Incompatible types
E e = c; Un C n'est pas forcément un E
D d = (D) c; Transtypage (Dowcasting), le compilateur ne fait pas de vérification ClassCastException Un F n'est pas un D
© Philippe GENOUD UGA Décembre 2017 20
Héritage et abstraction
classes abstraites
Philippe Genoud
©
© Philippe
Philippe GENOUD
GENOUD UGA
UJF Décembre 2017
2009 21
Classes Abstraites
Exemple introductif
un grand classique les formes géométriques
on veut définir une application permettant de manipuler des formes géométriques
(triangles, rectangles, cercles…).
chaque forme est définie par sa position dans le plan
chaque forme peut être déplacée (modification de sa position), peut calculer son
périmètre, sa surface
largeur
v2
r
hauteur
x,y
x,y v1
x,y
Factoriser le code ?
}
}
définir des concepts incomplets qui devront être implémentés dans les sous classes
factoriser le code
les opérations 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 !!!)
© Philippe GENOUD UGA Décembre 2017 25
Classes abstraites
classe abstraite :
classe non instanciable, c'est à dire qu'elle n'admet pas
d'instances directes.
Impossible de faire new ClasseAbstraite(…);
mais une classe abstraite peut néanmoins avoir un ou des constructeurs
Une classe pour laquelle au moins une opération abstraite est déclarée est une
classe abstraite (l'inverse n'est pas vrai).
... ...
...
} la classe contient une méthode } la classe ne contient pas de
abstraite => elle doit être méthode abstraite => elle peut
déclarée abstraite être déclarée abstraite
© Philippe GENOUD UGA Décembre 2017 26
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.
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 souvent l'utilisation de classes abstraites.
classe concrète
classe abstraite
(périmètre() est
Rectangle ... FormeCirculaire héritée et non
concrétisée)
largeur : double rayon: double
hauteur : double utile que si spécialisée
périmètre() double
Disque Couronne
opération concrétisée rayonInterne : double
périmètre() double
périmètre() double
©
© Philippe
Philippe GENOUD
GENOUD UGA
UJF Décembre 2017
2009 31
Interfaces
Bill Venners Designing with Interfaces
One Programmer's Struggle to Understand the Interfaces
[Link]
Exemple introductif
abstract class Animal {
...
abstract void talk();
}
class Dog extends Animal { class Bird extends Animal { class Cat extends Animal {
... ... ...
void talk() { void talk() { void talk() {
[Link]("Woof!"); [Link]("Tweet"); [Link]("Meow");
} } }
} } }
Se passer du
polymorphisme ?
class Interrogator {
interface Talkative {
static void makeItTalk(Animal subject)
(Talkative { {
subject)
public void talk();
[Link]();
}
}
}
import [Link];
public interface Dessinable {
public static final int MAX_WIDTH = 1024;
int MAX_HEIGHT = 768;
public void dessiner(Graphics g);
void effacer(Graphics g);
}
[Link]
TexteDessinable
CuckooClock
String txt; réalisation
int x,y; RectangleDessinable
…
Font f; Color c
dessiner(Graphics g)
... opérations RectangleDessinable(double x,y,l,h ,
effacer(Graphics g);
dessiner(Graphics g) concrétisées Color c)
… dessiner(Graphics g)
effacer(Graphics g);
… effacer(Graphics g)
la liste des noms des interfaces à implémenter séparés par des Forme
virgules doit suivre le mot clé implements double x,y; //centre du cercle
Forme (double x, y)
class RectangleDessinable extends Rectangle double surface()
implements Dessinable , Enregistrable { double périmètre()
private Color c; deplacer(double dx,dy)
Une classe qui implémente une interface doit implémenter toutes les méthodes
abstraites définies dans l'interface et dans les interfaces dont elle hérite.
boolean isOpen()
void close()
représente une connexion ouverte vers une entité
telle qu’un dipositif hardware, un fichier, une “socket”
réseau, ou tout composant logiciel capable de
réaliser une ou plusieurs opérations d’entrée/sortie.
<< interface >> << interface >>
ReadableByteChanel WritableByteChanel
package [Link];
interface ByteChannel extends ReadableByteChanel, WriteableByteChanel {
}
By incorporating interfaces into your next project, you will notice benefits throughout
the lifecycle of your development effort. The technique of coding to interfaces rather
than objects will improve the efficiency of the development team by:
Allowing the development team to quickly establish the interactions among the
necessary objects, without forcing the early definition of the supporting objects
Enabling developers to concentrate on their development tasks with the knowledge
that integration has already been taken into account
Providing flexibility so that new implementations of the interfaces can be added into
the existing system without major code modification
Enforcing the contracts agreed upon by members of the development team to ensure
that all objects are interacting as designed
dessiner(Graphics g)
effacer(Graphics g)
dessiner(Graphics G, Color c)
Clock
…
CuckooClock TexteDessinable
… String txt;
dessiner(Graphics g) int x,y;
effacer(Graphics g); Font f; ...
… …
dessiner(Graphics g)
effacer(Graphics g);
dessiner(Graphics g)
effacer(Graphics g)
dessiner(Graphics G, Color c)
Clock
…
1ère solution :
CuckooClock TexteDessinable Modifier le code de toutes les classes
… String txt; implémentant l'interface
dessiner(Graphics g) int x,y; (encore faut-il le pouvoir)
effacer(Graphics g); Font f; ...
dessiner(Graphis g, …
Color
… c) dessiner(Graphics g)
effacer(Graphics g);
dessiner(Graphics g,
Color c)
dessiner(Graphics g)
effacer(Graphics g)
Clock
… <<interface>>
DessinableColoriable
dessiner(Graphics g , Color c)
CuckooClock TexteDessinable
Clock
…
CuckooClock TexteDessinable
… String txt;
dessiner(Graphics g) int x,y;
effacer(Graphics g); Font f; ...
… …
dessiner(Graphics g)
effacer(Graphics g);
Java7-
une méthode déclarée dans une interface ne fournit pas d'implémentation
* titre inspiré du titre de l'article Java 8 : du neuf dans les interfaces ! du blog d'Olivier Croisier
[Link]
les classes filles sont libérées de fournir une implémentation d'une méthode default, en
cas d'absence d'implémentation spécifique c'est la méthode par défaut qui est invoquée
public interface Itf { public class Cls implements Itf {