java - implémentation des concepts objets

Post on 05-Dec-2014

943 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

 

TRANSCRIPT

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

top related