View
944
Download
1
Category
Preview:
DESCRIPTION
Citation preview
Implémentation de concepts objets
en langage Java
Jean David Olekhnovitchjd@olek.fr
Version du 11/10/13
mercredi 23 octobre 13
UML et langages objets
• La plupart des langages sont orientés objet
• Les concepts objets principaux sont toujours présents (encapsulation, héritage..)
• Certaines notions avancées sont survolées ou oubliées (agrégation, héritage multiple, polymorphisme, interface..)
• Tous les langages OO sont égaux, mais certains sont plus égaux que d’autres...
mercredi 23 octobre 13
Usages d’écriture en Java• Quelques règles à suivre
• UneClasse
• UNECONSTANTE (on tolère UNE_CONSTANTE)
• autreChoseQuUneClasse
• Notation Hongroise
• maMethodeAMoi
• plutôt que ma_methode_a_moi
• Pas d’accent, ni d’espace dans les noms
mercredi 23 octobre 13
Définition d’une classe• Rappel : une classe est un modèle
• En Java, tout est encapsulé dans des classes
public class UneClasse{
}
• Un fichier = une classe, et une classe par fichier
• Nom du fichier = nom de la classe !
• Casse comprise !
mercredi 23 octobre 13
Une classe en Java• Toutes les classes en Java héritent
implicitement de la classe Object
• Utilisent les classes du package java.lang
• Et implémentent un constructeur par défaut sans paramètre
import java.lang.*;
public class UneClasse extends Object{ public UneClasse() { super(); } }
mercredi 23 octobre 13
Classes et objets
• Les objets sont les instances de classe
Facture f; // création variablef=new Facture(); // instanciation, et affectation
• Version condensée :
Facture f=new Facture(); // création, instanciation, et affectation
mercredi 23 octobre 13
Attributs et méthodes• Les classes seront constituées des attributs et
méthodes
public class Facture{ double prixHT; // attributs double tva; double getPrixTTC() // méthode { return prixHT*(tva/100+1); } }
Facture
prixHTtva
getPrixTTC()
mercredi 23 octobre 13
Utilisation d’une instance
public static void main(String[] args){ Facture f=new Facture(); f.prixHT=120; f.tva=19.6; double result=f.getPrixTTC();}
Syntaxe instance.méthode()
Syntaxe instance.attribut
mercredi 23 octobre 13
Encapsulation• L’encapsulation dans un objet (la “boîte
noire”) est définie en Java par les mots clés de visibilité
public class Vehicule{ private int vitesse; public void setVitesse(int newvitesse) { if(newvitesse>=0) vitesse=newvitesse; }}
L’attribut est ici privé, il fait partie de l’implémentation
La méthode est publique, elle
constitue
mercredi 23 octobre 13
Getters et Setters• La visibilité des attributs se fait via des
accesseurs : GET et SET
private int prix;public int getPrix(){ return prix;}public void setPrix(int newprix){ prix=newprix;}
mercredi 23 octobre 13
Exemple du répondeurpublic class Repondeur{ private boolean etat; private String message; public void allumer() { etat=true; } public void enregMessage(msg) { message=msg; } public String lireMessage() { return message; }}
Repondeur
etatmessage
allumer()eteindre()enregMessage(msg)lireMessage()
mercredi 23 octobre 13
Naissance d’un objet
mercredi 23 octobre 13
Naissance d’un objet
c
Client c;
mercredi 23 octobre 13
Naissance d’un objet
c=new Client();
c
Client c;
mercredi 23 octobre 13
Naissance d’un objet
c=new Client();Instance
c
Client c;
mercredi 23 octobre 13
Naissance d’un objet
c=new Client();Instance
Constructeur
c
Client c;
mercredi 23 octobre 13
Naissance d’un objet
c=new Client();Instance
Constructeur
c
Pointe vers une instanceen mémoire
Client c;
mercredi 23 octobre 13
Mort d’un objet
c=null;ou
c=new Client(); // autre instance
Instance
c
c ne pointe plus
sur l’instance
X
Garbage Collector
mercredi 23 octobre 13
Construction• Le constructeur est appelé lors de
l’instanciation d’un objet
• Il permet d’initialiser l’instance pour qu’elle soit “propre” dès le début
• Si pas de constructeur : constructeur implicite sans paramètre
• Si constructeur : le constructeur implicite n’existe plus
• Il est possible de surcharger le constructeur
mercredi 23 octobre 13
Le constructeur• Nom de la méthode = nom de la classe
• Aucun paramètre de sortie (même pas void)public class Client{ private String nom; public Client() // constructeur { }
public Client(String newnom) // surcharge constructeur { nom=newnom; }}
Client c=new Client();Client c=new Client(“Bob”);
mercredi 23 octobre 13
Quelques règles à suivre
• Une interface doit être simplifiée au maximum et adaptée aux besoin de l’utilisateur
• L’interface doit être documentée
• L’instance doit en permanence être cohérente en mémoire
• Initialisation propre via les constructeurs
• Protection des données via les setters
mercredi 23 octobre 13
Le mot clé this
• Représente l’instance en cours
• Utilisé à l’intérieur même de la classe
mercredi 23 octobre 13
this pour lever une ambiguité
public class Client{ private String nom; public Client(String nom) { this.nom=nom; }}
Le paramètre d’entréeL’attribut
Il est conseillé d’utiliser this systématiquement pour lever tout
ambiguité
mercredi 23 octobre 13
this pour appeler un constructeur
public class Client{ private String nom; public Client() // constructeur { this(“Nom par défaut”); }
public Client(String nom) // surcharge du constructeur { this.nom=nom; }}
Client c1=new Client();Client c2=new Client(“Bob”);
mercredi 23 octobre 13
this pour appeler un constructeur
public class Client{ private String nom; public Client() // constructeur { this(“Nom par défaut”); }
public Client(String nom) // surcharge du constructeur { this.nom=nom; }}
Client c1=new Client();Client c2=new Client(“Bob”);
X
X
N’écrire qu’un constr avec param permet
d’interdire la construction sans paramètre
mercredi 23 octobre 13
this pour envoyer l’instance a une autre
méthode
public uneMethode() { uneInstance.uneAutreMethode(this); }
mercredi 23 octobre 13
Exemple de rétro-appel avec this
public class Carrossier{ public void peindre(Voiture v,String coul) { v.aileDroite=coul; v.capot=coul; ... }}
public class Voiture{ public Aile aileDroite; public Capot capot; ... public void ordonneCarrossier() { Carrossier c=new Carrossier(); c.peindre(this,”rouge”); }} Le carrossier agira
sur moi-même
Cette liaison est une association
mercredi 23 octobre 13
L’association• Liaison simple entre deux classes
• Ex : un client utilise un TPE (terminal de paiement)
public class Client{ void paiement(Tpe terminal) { ... terminal.saisieCode(“1234”); ... }}
L’instance de l’élément associé vient de
l’extérieur
mercredi 23 octobre 13
L’agrégation• Liaison plus “intime” entre deux classes
• Ex : on intègre un moteur à une voiture
public class Voiture{ private Moteur moteur; public Voiture(Moteur m) { this.moteur=m; }}
L’instance de l’élément agrégé vient de
l’extérieur
L’élément agrégé est un attribut
Moteur m=new Moteur(); Voiture v=new Voiture(m); ... v=null; // on tue l’instance de voiture, // mais le moteur m existe toujours
mercredi 23 octobre 13
La composition• Forme forte de l’agrégation
• Ex : un humain est composé d’une tête
public class Humain{ private Tete t; public Humain() // constructeur { this.t=new Tete(); }} L’instance est
construite à l’intérieur de
l’objet
L’élément composé est un attribut
Humain h=new Humain(); ... h=null; // on tue l’instance de humain, // ainsi qu’implicitement sa tête
mercredi 23 octobre 13
Agrégation vs Composition
mercredi 23 octobre 13
Agrégation vs Composition
Voiture
Moteur mot
v
Moteur
m
Humain
Tete tete
Tete
h
mercredi 23 octobre 13
Agrégation vs Composition
Voiture
Moteur mot
v
Moteur
m
Humain
Tete tete
Tete
h
XX
X
mercredi 23 octobre 13
Agrégation vs Composition
Voiture
Moteur mot
v
Moteur
m
Humain
Tete tete
Tete
h
XX
X
XX
X XX
mercredi 23 octobre 13
Agrégation vs Composition
Voiture
Moteur mot
v
Moteur
m
Humain
Tete tete
Tete
h
XX
X
XX
X XX
L’instance de moteur reste “en
vie”
La tête “meurt”
avec l’instance composée
mercredi 23 octobre 13
Association (ou agrégation) bidirectionnelle
• Une association peut être mentionnée des deux côtés
• Cela reste optionnel
• Réfléchir à l’utilité d’une telle liaison
public class Voiture{ private Personne conducteur;}
public class Personne{ private Voiture maVoiture;}
mercredi 23 octobre 13
Cardinalités multiples
• Lorsque la liaison est de type 0..N ou 1..N, on va stocker les instances dans un tableau ou une liste chainée
public class Page{ // souvent peu utile private Livre monLivre;}
public class Voiture{ // nombre d’éléments fixes private Roue[] roues;}
public class Livre{ private ArrayList<Page> pages;}
mercredi 23 octobre 13
Classes d’association
• En UML, c’est une classe à part
• En pratique, c’est une classe comme les autres, contenant :
• Les attributs de la classe d’association
• Les informations permettant d’intégrer la notion d’association :
• Tuple formé des pointeurs vers les 2 (ou plus) classes associées
• Rarement des méthodes
• Mieux vaut remplacer par une classe à part entière dès l’analyse
mercredi 23 octobre 13
Implémentation d’une classe d’association
public class Vol{ ...}
public class InfosEscales{ private Vol vol; private Aeroport aeroport; private Time heureDepart; private Time heureArrivee;}
public class Aeroport{ ...}
mercredi 23 octobre 13
L’héritage
• Conceptuellement : hiérarchisation de thèmes voisins (ex : Véhicule / Voiture / Break)
• Pragmatiquement : possibilité de regrouper du code commun à différentes classes
mercredi 23 octobre 13
L’héritage en tant que généralisation
• Permet de factoriser du code
Vehicule
MotoVoiture
Généralisation
public class Moto{ private Moteur m;}
public class Voiture{ private Moteur m;}
mercredi 23 octobre 13
L’héritage en tant que généralisation
• Permet de factoriser du code
Vehicule
MotoVoiture
Généralisation
public class Vehicule{ protected Moteur m;}
public class Voiture extends Vehicule{ ...}
public class Moto{ private Moteur m;}
public class Voiture{ private Moteur m;}
mercredi 23 octobre 13
L’héritage en tant que spécialisation
• Permet de reprendre une classe en la modifiant
Fenetre
BoiteDialogue
Spécialisation
public class Fenetre{ ...}
public class BoiteDialogue extends Fenetre{ ...}
mercredi 23 octobre 13
Mot-clé super
• S’utilise comme this
• Représente non pas sa propre instance, mais l’instance de la classe mère
• Usages :
• Appeler un constructeur de la classe mère
• Appeler une méthode de la classe mère
• Lever une ambiguité sur des méthodes de mêmes noms dans la classe mère/fille
mercredi 23 octobre 13
Appel constructeur classe mère
public class Produit{ protected int ref; public Produit(int ref) { this.ref=ref; }}
public class Livre extends Produit{ protected int nbpages; public Livre(int ref,int nbpages) { super(ref); this.nbpages=nbpages; }}
Appel constructeur classe
mère L’appel au constructeur de la classe mère est impérativement la
première instruction du constructeur
• Attention, on n’hérite pas du constructeur de sa classe mère !
mercredi 23 octobre 13
Constructeurs et héritage
• Quelques règles à comprendre :
• Pas d’héritage des constructeurs
• Il est impératif d’appeler le constructeur de la classe mère
• En cascade jusqu’à Object()
• Si l’on ne le fait pas, Java effectue un appel implicite de type super()
mercredi 23 octobre 13
Exemple posant problèmepublic class Mere{ public Mere(int i) { ... }}
public class Fille extends Mere{ public Fille(int i) { ... }}
• Pas d’appel au constructeur parent dans Fille
• Du coup, Java tente d’en faire un implicite
• super()
• Mais il n’y a pas de constructeur sans paramètre dans Mere -> erreur
• Il faut insérer un super(i) dans Fille
• appel implicite de type super()mercredi 23 octobre 13
Exemple un peu tordupublic class Mere{ public Mere(int i) { ... } public Mere() { ... }}
public class Fille extends Mere{ // pas de constructeur}
• Fille f=new Fille(); est autorisé
• Fille f=new Fille(12); est interdit !
• Pas de constructeur = Constructeur implicite sans paramètre
• Ce constructeur fait un appel implicite à super()
• Le constructeur Mere() est donc appelé
mercredi 23 octobre 13
Surcharge de méthodes• Permet de réécrire une méthode de la
classe mère dans une classe fille
• Utile lors de la spécialisation d’une classe
• C’est également la base du polymorphisme
public class Voiture{ ... public void ouvrePorteCoffre() { ... }}
public class Break extends Voiture{ ... public void ouvrePorteCoffre() { ... // éventuellement appel a méthode mère super.ouvrePorteCoffre(); ... }}
mercredi 23 octobre 13
Masquage d’attributs• Permet de réécrire un attribut de la classe
mère dans une classe fille
• Sert essentiellement pour redéfinir les initialisations
• On ne peut changer le type
public class Voiture{ private int vitesseMax=160;}
public class VoitureSport extends Voiture{ private int vitesseMax=250;}
mercredi 23 octobre 13
Redéfinition de méthodes
• N’est pas lié à l’héritage
• Permet la réécriture de méthodes dans une même classes
• Avec un nombre d’attributs différents
• ou des attributs de nature différentes
• Utile pour fournir une interface de classe s’adaptant aux besoins de l’utilisateur
public class ObjetGraphique{ public void setColor(String col) { ... } public void setColor(int numcol) { ... } public void setColor(int r,int v,int b) { ... }}
mercredi 23 octobre 13
Polymorphisme• Permet un traitement qui va s’adapter au
contexte
• Dans la pratique : une méthode surchargée via une structure d’héritage
public class Forme{ public double calculeAire() { ... }}
public class Cercle extends Forme{ public double calculeAire() { ... }}
public class Rectangle extends Forme{ public double calculeAire() { ... }}
mercredi 23 octobre 13
Utilisation du polymorphisme
• Permet d’uniformiser des traitements hétérogènes
AVANT :{ // cumul aire double aire=0; for(...) { Forme formeCourante=...; if(formeCourante==cercle) aire=aire+formeCourante.calculeAireCercle(); if(formeCourante==rectangle) aire=aire+formeCourante.calculeAireRectangle(); }}
APRES :{ // cumul aire double aire=0; for(...) { Forme formeCourante=...; aire=aire+formeCourante.calculeAire(); }}
mercredi 23 octobre 13
Downcasting• Transtypage permettant de considérer une
instance “comme si” elle était de sa classe mère
• Facilite les traitements polymorphe
{ Cercle c=new Cercle(); ... Forme f=(Forme)c; // downcasting
Forme f2=new Cercle(); // downcast dès l’instanciation}
mercredi 23 octobre 13
Upcasting• Transtypage permettant de “préciser” le type
d’une instance
• Parfois risqué (risque de plantage à l’exécution)
{ Produit p=liste.get(i); ... Livre l=(Livre)p; // upcasting int nb=l.getNbPages();}
mercredi 23 octobre 13
Méthode abstraite
• Dans l’implémentation du polymorphisme, la méthode “mère” n’a souvent pas de sens
• Ex : on ne peut pas calculer “comme ça” l’aire d’une forme géométrique
• Mais toutes les formes ont leur aire calculable
• On utilise la notion de méthode abstraite
mercredi 23 octobre 13
Mise en place méthode abstraitepublic class Forme
{ public double calculeAire() { return 0; }}
Avant :
public abstract class Forme{ public abstract double calculeAire();}
Après :
• Si méthode abstraite :
• classe abstraite
• on ne peut l’instancier
• obligation d’implémentation de la méthode dans les classes filles
• Une méthode abstraite fait partie de l’interface
Forme f=new Forme();
mercredi 23 octobre 13
Intérêts du polymorphisme avec abstract
• Empêche l’instanciation de la classe mère qui de toute manière ne représente rien concrétement
• une instance de “Forme”, sans autre détail, ne pourrait être exploitée
• Oblige le développeur a implémenter la méthode polymorphe dans toutes les classes filles
• Empêche les incohérences dans le cas d’une écriture de nouvelles classes filles
mercredi 23 octobre 13
L’héritage multiple• En résumé :
• Il n’y a pas d’héritage multiple en Java
• Version plus détaillée :
• Pas d’héritage d’implémentation
• la factorisation de code multiple peut poser des problèmes d’ambiguités
• Mais un héritage d’interface
• Permet d’étendre le polymorphisme
mercredi 23 octobre 13
Comment représenter l’héritage d’interface
• Notion d’interface explicitée
• Permet de faire un héritage sans aucune implémentation
• Equivalent des “classes virtuelles pures” en C++
• Fonctionne comme une classe abstraite qui ne contiendrait que des méthodes abstraites
• Permet un héritage multiple
• Peut être cumulé à un héritage d’implémentation
mercredi 23 octobre 13
Comprendre la notion d’interface
• Forme faible d’héritage
• Expurgée de notion d’extension
• On parle plutôt d’affectation de capacités
• D’où le suffixe “-able” : a la capacité de...
mercredi 23 octobre 13
Exemple d’interface
public interface Colorable{ public void setColor(String nomcol);}
public class Forme implements Colorable{
public void setColor(String nomcol) { ... }}
Pas besoin de préciser “abstract”
Implémentation de l’interface
Représente l’héritage d’interface
mercredi 23 octobre 13
Cumul interface/héritage classique
• On peut cumuler au sein d’une même classe
• Un héritage d’implémentation (extends...)
• Un ou plusieurs héritages d’interface (implements...)
• Ex :
public class Voiture implements Colorable, Crashable, extends Vehicule
mercredi 23 octobre 13
Utilisation d’une interface
• Traitements polymorphes comme avec une méthode abstraite
public void paintItBlack(ArrayList<Colorable> liste){ for(int i=0;i<liste.size();i++) { Colorable elem=liste.get(i); elem.setColor(“noir”); }}
mercredi 23 octobre 13
Hétérogénéité possible d’une interface
• L’interface permet de créer un “dénominateur commun” a des éléments très divers
• Permet de faire des traitements polymorphes en dehors d’un contexte d’héritage
ArrayList<Colorable> liste=new ArrayList<Colorable>();liste.add(new Voiture());liste.add(new Cercle());liste.add(new Jouet());liste.add(new Perruque());
this.paintItBlack(liste);
mercredi 23 octobre 13
Recommended