ENSTA IN204 Introduction JAVA - PowerPoint PPT Presentation

1 / 48
About This Presentation
Title:

ENSTA IN204 Introduction JAVA

Description:

On aimerait pouvoir appliquer les traitements g n riques pr c dents une m me ... On aimerait bien (mais on ne peut pas) crire : class Voiture extends Vehicule, ... – PowerPoint PPT presentation

Number of Views:47
Avg rating:3.0/5.0
Slides: 49
Provided by: olivier102
Category:

less

Transcript and Presenter's Notes

Title: ENSTA IN204 Introduction JAVA


1
ENSTA IN204Introduction à JAVA
LIP6 cours L3 POBJ Programmation par Objets
(en Java)
  • Olivier Sigaud
  • LIP6/AnimatLab
  • olivier.sigaud_at_lip6.fr
  • 01.44.27.88.53

2
Plan du cours 5
  • Le polymorphisme
  • Labstraction
  • L'héritage multiple
  • Les interfaces
  • Les problèmes du polymorphisme

inséparables
inséparables
3
Polymorphisme(rappel)
4
Héritage et traitements
  • L'héritage permet d'organiser les données sous
    forme de classes de façon à coller à la
    sémantique du domaine modélisé
  • Mais l'héritage permet aussi d'organiser les
    traitements de façon à éviter les répétitions de
    code
  • Pour utiliser correctement lhéritage, il faut du
    polymorphisme et de l'abstraction

5
Polymorphisme exemple (1)
  • class Vehicule
  • void demarrer()
  • class Garagiste
  • public static void garer(Vehicule v)
  • v.demarrer()
  • class Main
  • public static void main(String args)
  • Voiture voiture new Voiture()
  • Garagiste.garer(voiture)
  • Bien que, syntaxiquement, v soit un véhicule,
    l'objet est une voiture

class Voiture extends Vehicule void
demarrer()
Méthode appelée ici
6
Polymorphisme exemple (2)
  • class Vehicule
  • class Garagiste
  • public static void garer(Vehicule v)
  • v.demarrer()
  • class Main
  • public static void main(String args)
  • Voiture voiture new Voiture()
  • Garagiste.garer(voiture)
  • Javac vérifie syntaxiquement que la classe
    mentionnée possède bien la méthode

class Voiture extends Vehicule void demarrer()

Ne compile pas !!!
7
Polymorphisme implicite synthèse
  • Java connaît la classe de l'objet même si ce
    n'est pas le type spécifié dans le code source
  • Si l'objet passé en paramètre (Vehicule v) est
    une Voiture, il appellera la méthode demarrer()
    de la classe Voiture
  • Il suffit que Voiture hérite de Vehicule
  • Si la méthode appelée existe pour les deux types,
    alors Java appellera celle de la classe de
    l'objet, même si le type mentionné est différent
  • Si la méthode appelée n'existe pas pour le type
    spécifié, alors Java refuse de compiler

8
Polymorphisme implicite problème
  • Pour que le code précédent compile, il faut que
    la classe Vehicule dispose d'une méthode
    demarrer().
  • Mais il se peut que l'on ne soit pas capable
    d'écrire le code d'une méthode démarrer pour une
    classe Vehicule représentant un véhicule
    quelconque.
  • Deux solutions
  • Le polymorphisme explicite
  • Les méthodes (et classes) abstraites

9
Polymorphisme explicite
  • Si lon veut appeler une méthode qui n'existe que
    pour le type spécifique, alors il faut caster
    , c'est-à-dire déclarer un type plus spécifique
    pour l'objet
  • Le cast est utile à la compilation il
    permet dindiquer au compilateur que lobjet est
    dun type plus spécifique et donc de vérifier que
    la méthode spécifique qui sera appelée existe
    bien
  • Si l'on caste alors que la classe de l'objet
    n'est pas compatible avec le type casté, Java
    lève à l'exécution l'exception
    ClassCastException

10
Polymorphisme explicite exemple (1)
  • class Vehicule
  • class Garagiste
  • public static void garer(Vehicule v)
  • ((Voiture)v).demarrer()
  • class Main
  • public static void main(String args)
  • Voiture voiture new Voiture()
  • Garagiste.garer(voiture)
  • Problème la méthode garer(Vehicule v) n'est
    plus générique, elle ne marche que pour les
    voitures

class Voiture extends Vehicule void
demarrer()
Java sait que l'objet sera une voiture
11
Polymorphisme explicite exemple (2)
  • class Vehicule
  • class Garagiste
  • public static void garer(Vehicule v)
  • ((Voiture)v).demarrer()
  • class Main
  • public static void main(String args)
  • Camion cam new Camion()
  • Garagiste.garer(cam)
  • Solution éventuelle vérifier le type de l'objet

class Voiture extends Vehicule void
demarrer()
ClassCastException à l'exécution
12
Polymorphisme explicite exemple (3)
  • class Vehicule
  • class Garagiste
  • public static void garer(Vehicule v)
  • if (v instanceof Voiture)
  • ((Voiture)v).demarrer()
  • else if (v instanceof Camion)
  • ((Camion)v).demarrer() //
  • Problème il faut connaître la liste des types
    possibles

class Voiture extends Vehicule void
demarrer()
13
Connaître le type d'un objet
  • if (v instanceof Vehicule) vérifie si v est un
    pointeur sur un objet de type Vehicule ou bien
    tout type plus spécifique que Vehicule
  • Si v est un Camion, renvoie true
  • if (v.getClass().getName().equals("Vehicule"))
    vérifie si v est un pointeur sur un objet de type
    Vehicule.
  • Si v est un Camion, renvoie false
  • Cette deuxième méthode fait appel à la
    réflexivité (quel est le nom de la classe de
    l'objet ?)
  • Problème la vérification explicite du type de
    lobjet est ce que lon cherche à éviter en POO

14
L'abstraction
15
Autre solution abstraction
class Voiture extends Vehicule void
demarrer()
  • class Vehicule
  • abstract void demarrer()
  • class Garagiste
  • public static void garer(Vehicule v)
  • v.demarrer()
  • class Main
  • public static void main(String args)
  • Voiture voiture new Voiture()
  • Garagiste.garer(voiture)
  • La classe Vehicule possède une méthode
    demarrer(), donc la compilation fonctionne.

A l'exécution, Java sait que l'objet est une
voiture
16
Méthode abstraite
  • Il peut être impossible de spécifier un
    comportement d'une classe générique
  • ex Forme calculerSurface()
  • Mais on peut avoir besoin de ce comportement au
    niveau générique
  • ex Forme trierParSurfacesCroissantes()
  • Dans ce cas, on déclare la méthode abstraite
  • public abstract void maMethode()
  • Toutes les classes qui en héritent doivent la
    spécifier, faute de quoi elles sont abstraites

17
Abstraction contraintes
  • Pour que lexemple précédent marche
  • On ne connaît pas le comportement demarrer()
    pour les objets de type Vehicule
  • Il ne faut pas pouvoir créer un objet du type
    Vehicule
  • Il faut que tout objet dun type qui hérite de
    Vehicule dispose dun comportement demarrer()
    concret
  • Donc toutes les méthodes abstraites doivent être
    redéfinies dans les classes filles
  • Les classes qui dérivent d'une classe abstraite
    doivent instancier toutes ses méthodes abstraites
    (sinon, elles sont abstraites à leur tour)

18
Classe abstraite
  • Une classe qui a une méthode abstraite est
    nécessairement abstraite
  • Lorsquune classe est abstraite, aucun objet du
    programme ne peut être instance de cette classe
  • Donc ne peut pas construire une instance d'une
    classe abstraite
  • Cependant, une classe abstraite a généralement
    des constructeurs
  • Ces constructeurs sont appelés lors de la
    construction des sous-classes (avec super())

19
Abstraction conséquence
class Voiture extends Vehicule void
ouvrirPorte()
  • class Vehicule
  • abstract void ouvrirPorte()
  • class Garagiste
  • public static void garer(Vehicule v)
  • v.ouvrirPorte() v.demarrer()
  • class Main
  • public static void main(String args)
  • Velo v new Velo()
  • Garagiste.garer(voiture)
  • On est contraint dajouter une méthode
    ouvrirPorte() dans la classe Velo, mais on ne
    sait pas la spécifier

class Velo extends Vehicule void ouvrirPorte()
???
20
Mélange explicite / implicite exemple
  • class Garagiste
  • public void garer(Vehicule v)
  • if (!(v instanceof Velo))
  • v.ouvrirPorte()
  • v.demarrer()
  • else ((Velo)v).pedaler()
  • La classe Velo ne possède pas de méthode
    ouvrirPorte()
  • Seule la classe Velo possède une méthode
    pedaler()
  • Dans un tel cas, pour que cela compile, il faut
    caster

21
Polymorphisme et abstraction synthèse
  • Pour définir un traitement abstrait, il faut
    choisir
  • Doter la classe abstraite d'une méthode abstraite
    et utiliser le polymorphisme implicite
  • Faire l'économie d'une méthode abstraite et
    caster
  • La première solution est souvent bien meilleure !
  • Mais cela suppose que toutes les classes
    concrètes disposent du traitement déclaré au
    niveau générique

22
Héritage multiple et interfaces
23
Imaginons un traitement générique
  • class Marchand extends Vector
  • public BienDeConso getProduit(int index)
  • return (BienDeConso)get(index)
  • public void vendre()
  • for (int i0iltsize()i)
  • BienDeConso bien getProduit(i)
  • bien.vendre()

24
Puis un deuxième
  • class Garagiste extends Vector
  • public Vehicule getVehicule(int index)
  • return (Vehicule)get(index)
  • public void garer()
  • for (int i0iltsize()i)
  • Vehicule v getVehicule(i)
  • v.garer()

25
L'héritage multiple
  • Une voiture est un véhicule et un bien de
    consommation (on peut la vendre et la conduire)
  • On aimerait pouvoir appliquer les traitements
    génériques précédents à une même instance de la
    classe Voiture.
  • On aimerait bien (mais on ne peut pas) écrire
  • class Voiture extends Vehicule, BienDeConso

26
L'héritage multiple le problème
class BienDeConso void afficher()
class Vehicule void afficher()
?
Voiture v new Voiture() v.afficher()
  • Problème si une classe hérite de 2 classes et
    si ces 2 classes ont 2 méthodes de même signature
    (ou 2 attributs de même nom), de laquelle
    (duquel) hérite la première ?
  • Permis en C, OCAML
  • Interdit en Java

27
L'héritage multiple le choix de JAVA
  • Problèmes dans les cas où
  • on pourrait déclencher deux traitements hérités
    différents à partir d'un même appel, en ne
    sachant pas lequel choisir
  • on pourrait avoir deux valeurs différentes pour
    le même attribut hérité, en ne sachant pas lequel
    choisir
  • Pas de problème avec une méthode abstraite elle
    sera redéfinie au niveau de la classe fille
  • Donc on peut faire de l'héritage multiple avec
    des classes purement abstraites (que des méthodes
    abstraites) et sans attributs

28
Les interfaces
  • Formellement équivalentes à une classe totalement
    abstraite
  • pas d'attributs (sauf éventuellement static)
  • que des méthodes abstraites
  • Exemple
  • interface Drawable
  • public void draw()
  • public void refresh()
  • public void erase()
  • Interfaces utiles (à connaître) Cloneable,
    Serializable

29
Interfaces pour quoi faire ?
  • Une classe qui implémente une interface doit
    implémenter toutes ses méthodes
  • contrat à respecter
  • Une classe peut implémenter plusieurs interfaces
  • Le polymorphisme fonctionne sur les interfaces
  • L'héritage entre interfaces fonctionne
  • Fournit un équivalent de l'héritage multiple
  • Mais on ne peut pas hériter du code

30
Héritage mulitple solution
interface BienDeConso void afficher() void
vendre() void acheter()
interface Vehicule void afficher() void
demarrer() void conduire()
  • class Voiture implements Vehicule, BienDeConso
  • public void afficher() // ici, le traitement
    d'affichage
  • public void vendre() // ici, le traitement de
    vente
  • public void acheter() // ici, le traitement
    d'achat
  • public void demarrer() // ici, le traitement
    de demarrage
  • public void conduire() // ici, le traitement
    de conduite

31
Interfaces que faire ?
  • Quand une classe ne contient que des méthodes
    abstraites, la définir plutôt comme une interface
  • Mettre dans une même interface des traitements
    qui vont bien ensemble (séparer en deux sil le
    faut)
  • Réfléchir aux traitements génériques dont on a
    besoin, les réaliser en manipulant des
    interfaces, puis implémenter ces interfaces.
  • Cest un principe fondamental pour la
    réutilisation des traitements génériques
  • Dès quon a de lhéritage multiple, utiliser des
    interfaces

32
Les problèmes de l'héritage
33
Polymorphisme les problèmes
  • Les problèmes liés au polymorphisme sont dus au
    fait que l'héritage ne sapplique pas
    correctement à la signature des méthodes
  • Java ne retrouve pas le vrai type
  • des paramètres
  • des valeurs de retour

34
Surcharge (rappel)
  • On appelle surcharge le fait davoir plusieurs
    méthodes qui ont le même nom au sein de la même
    classe
  • Les exemplaires de la méthode ont des paramètres
    différents
  • Ils peuvent avoir le même type de retour
  • Par contre, impossible davoir des types de
    retour différents pour les mêmes paramètres

35
Surcharge exemple
  • class Additionneur
  • static int somme(int a, int b) // 1
  • return (ab)
  • static int somme(int a, int b, int c) // 2
  • return (abc)
  • static float somme(float a, float b) // 3
  • return (ab)
  • static float somme(int a, int b) // interdit à
    cause de 1
  • return ((float)a(float)b)

36
Redéfinition
  • On appelle redéfinition dune méthode le fait de
    définir dans une classe fille une méthode qui a
    le même nom, les mêmes paramètres et le même type
    de retour quune méthode de la classe mère
  • La méthode redéfinie  masque  celle de la
    classe mère
  • Ne pas confondre avec surcharge paramètres
    identiques vs. différents

37
Redéfinition exemple
  • class Personne
  • void garer(Vehicule v)
  • v.demarrer()
  • //
  • class Garagiste extends Personne
  • void garer(Vehicule v)
  • v.fermerCapot() // appelle getCapot().fermer()
  • v.demarrer()
  • //
  • Les deux méthodes ont la même signature et
    appartiennent à deux classes liées par héritage
    gt il s'agit de redéfinition

38
Surcharge / redéfinition exemple
  • class Additionneur
  • static int somme(int a, int b)
  • return (ab)
  • static int somme(int a, int b, int c)
  • return (abc)
  • Dans Additionneur, les deux méthodes somme()
    appartiennent à la même classe mais n'ont pas la
    même signature gt il s'agit de surcharge
  • Dans Adder, on redéfinit la seconde méthode de
    Additionneur

class Adder extends Additionneur static int
somme(int a, int b, int c) return
(2abc)
39
Surcharge ou redéfinition ?
  • class Personne
  • void garer(Vehicule v)
  • v.demarrer()
  • //
  • class Garagiste extends Personne
  • void garer(Voiture v)
  • v.fermerCapot() // appelle getCapot().fermer()
  • v.demarrer()
  • //

40
Redéfinition et Surcharge
  • Quand il y a des paramètres différents, mais qui
    héritent les uns des autres
  • Ils sont vus comme effectivement différents
  • Cest donc un cas de surcharge
  • La méthode appelée sera celle dont les paramètres
    sont du type le plus spécialisé qui correspondent
    au type dappel
  • Le choix est fait à la compilation
  • Des exemples seront vus en TD

41
Hiérarchies complexesVers les Design Patterns
42
Les hiérarchies complexes (1)
Vehicule
VehiculeAXRoues
VehiculeA2Roues
VehiculeA4Roues
Rollers
Mobylette
Voiture
Camion
Trottinette
Velo
Fourgonnette
Exemple de mauvais critère de classification le
nombre de roues Les descendants ont peu de chose
en commun
43
Les hiérarchies complexes (2)
Vehicule
VehiculeAMoteur
VehiculeSansMoteur
Fourgonnette
Mobylette
Voiture
Camion
Trottinette
Velo
Rollers
Cette fois, le critère est structurant
44
Les hiérarchies complexes (3)
VehiculeSansMoteur
VehiculeAMoteur
Moteur monMoteur int nbRoues Clef
maClef demarrer()
int nbRoues propulser()
Si lon est amené à modifier une hiérarchie
complexe cela implique des réorganisations
majeures du code En particulier, des attributs et
des traitements doivent être partagés Importance
de la phase de conception préalable
45
Héritage et composition
46
Intérêt de lhéritage
  • class Sequenceur
  • MonVecteur data
  • public void reverse()
  • data.reverse()
  • class Sequenceur extends MonVecteur
  • // pas besoin de public void reverse()
    Sequenceur en hérite

47
Inconvénients de lhéritage
  • Induit un couplage fort entre les classes de la
    hiérarchie une modification de la classe mère
    induit des modifications de toutes les filles
  • Ralentit lexécution à cause du typage dynamique
  • Dans le livre Design patterns , vous trouverez
    quantité darguments en faveur de lutilisation
    des interfaces

48
Vers les Design Patterns
  • Dès quune application devient complexe
    (plusieurs niveaux dabstraction, packages,
    etc.), le coût de chaque remise en question
    devient élevé
  • Les Design Patterns peuvent être vus comme un
    ensemble de recettes utilisées très souvent et
    destinées à minimiser ces coûts
  • En deuxième partie du cours POBJ
Write a Comment
User Comments (0)
About PowerShow.com