programmation objet (en java)denoyer/courses/2006-2007/li314...leur(s) super-classe(s) ex. rectangle...

Post on 12-Jul-2020

0 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Programmation Objet (en Java)

UPMC – LicenceInformatique - LI 314

© 2006-2007 Frédéric PeschanskiLaboratoire d'Informatique de Paris 6

email: Frederic.Peschanski@lip6.fr

Plan du courspremière saison

Encapsulation et protection de l'information (cours 1 et 2)

Héritage et polymorphisme (cours 3 et 4)

Modélisation objet

Compilation, dispatch dynamique, clonage, etc.

Interfaces et paquetages (cours 5)

+ «tout» sur final et static

Plan du coursInterfaces et Paquetages

Interfaces

Du concret à l'abstrait

A quoi servent les interfaces ?

Paquetages et modularités

Point de vue paquetage

Glossaire O.O Java

Tous les mots-clés « orientés-objets » de la saison 1

+ «tout» sur final et static

I) Du concret vers l'abstrait

abstrait

concret

●Classes abstraites «pures»

●Classes abstraites

●Classes concrètes

●Interfaces

Classe concrète

Déclare (spécification)un type: le nom de la classe (+ lien d'héritage)Type et nom des attributsSignatures des méthodes (+ méthodes héritées)Accès: public, private, protected ou /* package */

Définit (implémentation)code associé à chaque (signature de) méthode

Niveau d'abstraction: 0% abstraitpour représenter/implémenter des concepts concrets

ex. Point, Voiture, Compte (banque), etc.

Exemple: la classe Point

public class Point extends Figure {private double x;private double y;

public Point(String nom,double x,double y) {super(nom);this.x=x;this.y=y;

}

public String getX() { return x; }

public String getY() { return y; }

public void translater(double tx,double ty) {x+=tx;y+=ty;}

public String toString() {return super.toString()+":("+x+","+y+")";

}}

public class Point extends Figure {private double x;private double y;

public Point(String nom,double x,double y) {super(nom);this.x=x;this.y=y;

}

public String getX() { return x; }

public String getY() { return y; }

public void translater(double tx,double ty) {x+=tx;y+=ty;}

public String toString() {return super.toString()+":("+x+","+y+")";

}}

Point

+ Point(x : double, y : double)+ getX() : double+ getY() : double+ translater(tx : double, ty : double) : void+ toString() : String

hérite de la classe Figure (cf. plus loin)

Représentation UML:vision client

Classe concrète: Possibilités

Utiliser:Déclarer des variables du type de la classeConstruire des instances de la classe (new)Invoquer des méthodes déclarées sur les instances de la classe

Hériter:Définir des sous-classes également concrètes

Classe abstraiteDéclare (spécification)

un type: le nom de la classe (+ lien d'héritage abstrait)Type et nom des attributsSignatures des méthodes (+ méthodes héritées)

méthodes concrètes (avec implémentation)méthodes abstraites (sans implémentation)

Accès: public, private, protected ou /* package */

Définit (implémentation)code associé à chaque méthode concrète

Exemple: la classe Figure

public abstract class Figure {private String nom;

protected Figure(String nom) {this.nom=nom;

}

public String getNom() { return nom;

}

public abstract void translater(double tx,double ty);

public String toString() {return nom;

}}

public abstract class Figure {private String nom;

protected Figure(String nom) {this.nom=nom;

}

public String getNom() { return nom;

}

public abstract void translater(double tx,double ty);

public String toString() {return nom;

}}

Représentation UML (point de vue client)

Figure

+ getNom() : String+ translater(tx: double, ty : double) : void+ toString() : String

« abstract »

Classe abstraites: Possibilités

Utiliser:Déclarer des variables du type de la classeConstruire des instances de la classe (new)Invoquer des méthodes déclarées sur les instances de sous-classes concrètes

Hériter:Définir des sous-classes

sous-classes abstraitessous-classes concrètes

Important: nécessité d'implémenter toutes les méthodes abstraites

Cas particulier:classe abstraite «pure»

Déclare (spécification)un type: le nom de la classe (+ lien d'héritage abstrait)pas d'attributSignatures des méthodes (+ méthodes héritées)

méthodes abstraites uniquement (sans implémentation)

Accès: public, private, protected ou /* package */

Ne définit pas d'implémentationNiveau d'abstraction: 100% abstrait

concepts 100% abstraitex. Catégorie («abstract nonsense») en théorie des catégories

Interfaces

Déclare (spécification)un type: le nom de l'interface (+ héritage d'interface)pas d'attributSignatures des méthodes (+ signatures héritées)

Important: signatures uniquement

Accès: public uniquement

Ne définit pas d'implémentationNiveau d'abstraction: 100% abstrait

proche classe abstraite « pure » mais accès uniquement public et héritage uniquement dans les interfaces

Exemple: l'interface Mesurable

public interface Mesurable {public double calculeSurface();public double calculePourtour();

}

public interface Mesurable {public double calculeSurface();public double calculePourtour();

}

Représentation UML (point de vue client uniquement)

Mesurable+ calculeSurface() : double+ calculePourtour() : double

Remarques: ● pas de place pour des attributs● tout en italique (100% abstrait)● accès public (+) obligatoire

«interface»

Interfaces: Possibilités

Utiliser:Déclarer des variables du type de l'interfaceInvoquer des méthodes déclarées sur des instances de classes qui implémentent l'interface

Implémenter: implementsDéfinir des classes «compatibles» avec l'interface

Remarque: le type de la classe devient sous-type de l'interface (à retenir: interface = type)

Hériter: (héritage d'interface)Définir des sous-interfaces héritant d'une ou de plusieurs super-interface(s)Très intéressant mais peu étudié en POBJ (cf. M1)

Exemple: la classe Rectangle mesurable

public class Rectangle extends Figure implements Mesurable {private double x,y;private double l,h;

public Rectangle(String nom,double x,double y,double l,double h) {super(nom);this.x=x;this.y=y;this.l=l;this.h=h;

}

public String getX() { return x; }

public String getY() { return y; }

public String getLongueur() { return l; }

public String getHauteur() { return h; }

public void translater(double tx,double ty) {x+=tx;y+=ty;

}// Ca continue ...

public class Rectangle extends Figure implements Mesurable {private double x,y;private double l,h;

public Rectangle(String nom,double x,double y,double l,double h) {super(nom);this.x=x;this.y=y;this.l=l;this.h=h;

}

public String getX() { return x; }

public String getY() { return y; }

public String getLongueur() { return l; }

public String getHauteur() { return h; }

public void translater(double tx,double ty) {x+=tx;y+=ty;

}// Ca continue ...

Exemple: la classe Rectangle (suite)// La suite ...

// Implémentation OBLIGATOIRE des méthodes de// l'interface implémentée

public double calculeSurface() { return l*h;

}

public double calculePourtour() { return 2*(l+h);

}

}

// La suite ...

// Implémentation OBLIGATOIRE des méthodes de// l'interface implémentée

public double calculeSurface() { return l*h;

}

public double calculePourtour() { return 2*(l+h);

}

}

Important: toutes les méthodes de l'interface doivent être implémentées

Exemple 2: la classe Cercle

public class Cercle extends Figure implements Mesurable {private double x,y;private double r;

public Cercle(String nom,double x,double y,double r) {super(nom);this.x=x;this.y=y;this.r=r;

}

public String getX() { return x; }

public String getY() { return y; }

public String getRayon() { return r; }

public void translater(double tx,double ty) {x+=tx;y+=ty;

}

// Ca continue ...

public class Cercle extends Figure implements Mesurable {private double x,y;private double r;

public Cercle(String nom,double x,double y,double r) {super(nom);this.x=x;this.y=y;this.r=r;

}

public String getX() { return x; }

public String getY() { return y; }

public String getRayon() { return r; }

public void translater(double tx,double ty) {x+=tx;y+=ty;

}

// Ca continue ...

Exemple 2: la classe Cercle (suite)// La suite ...

// Implémentation OBLIGATOIRE des méthodes de// l'interface implémentée

public double calculeSurface() { return Math.PI*r*r;

}

public double calculePourtour() { return 2*Math.PI*r;

}

}

// La suite ...

// Implémentation OBLIGATOIRE des méthodes de// l'interface implémentée

public double calculeSurface() { return Math.PI*r*r;

}

public double calculePourtour() { return 2*Math.PI*r;

}

}

Important: toutes les méthodes de l'interface doivent être implémentées

Représentation UML (point de vue client)

Mesurable+ calculeSurface() : double+ calculePourtour() : double

«interface»Figure

+ getNom() : String+ translater(tx: double, ty : double) : void+ toString() : String

« abstract »

Rectangle

+ Rectangle(x : double, y : double, l : double, h : double)+ getX() : double + getY() : double+ getLongueur() : double + getHauteur() : double+ translater(tx : double, ty : double) : void+ calculeSurface() : double+ calculePourtour() : double

Cercle

+ Rectangle(x : double, y : double, l : double, h : double)+ getX() : double + getY() : double+ getLongueur() : double + getHauteur() : double+ translater(tx : double, ty : double) : void+ calculeSurface() : double+ calculePourtour() : double

Lien d'implémentation

Relation implementsclasse C implements interface I

C « EST » I (ou « EST UN » mais plus rare)ex. Rectangle « EST » Mesurableex. Cercle « EST » Mesurableex. Figure « EST » Mesurable => ne marche pas !

Représentation UML:I

+ mehode(T1,...,TN) : T

«interface»

C+ mehode(T1,...,TN) : Tetc...

Les interfaces en pratique

1) Capacités communes (ex. Mesurable)● favorise le polymorphisme

2) Traverser des hiérarchies de classes séparées● compatibilité entre classes sans super-classe commune

3) Suppléer l'héritage● «économiser» le lien d'héritage● simuler l'héritage multiple

4) Cas particuliers● interfaces marqueurs (ex. Clonable, Serializable)● interfaces standards (ex. Comparable)

(1) Capacités communes

Des classes distinctes partagent une même capacité.

ex. Rectangle et Cercle partagent la capacité d'être Mesurable

... mais cette capacité dépasse le cadre de leur(s) super-classe(s)

ex. Rectangle et Cercle héritent de Figure mais toutes les Figure ne sont pas forcément Mesurable

favorise le polymorphismesi on utilise le type de l'interface, ex. Mesurable

on peut référencer des instances de n'importe quelle classe implémentant l'interface

Exemple: surface totale

public static double calculeSurface(ArrayList<Mesurable> figs) {double surface = 0.0;for(Mesurable fig : figs) {

surface += fig.calculeSurface(); // OK car mesurable ...}return surface;

}

// dans le main ...public static void main(String[] args) {ArrayList<Mesurable> list = new ArrayList<Mesurable>();list.add(new Cercle(2,2,3)); // OK car mesurable ...list.add(new Rectangle(2,2,3,4)); // OK car mesurable ...// list.add(new Point(2,2)); // KO car non-mesurable ...System.out.println("Surface totale = "+calculeSurface(list));

}

public static double calculeSurface(ArrayList<Mesurable> figs) {double surface = 0.0;for(Mesurable fig : figs) {

surface += fig.calculeSurface(); // OK car mesurable ...}return surface;

}

// dans le main ...public static void main(String[] args) {ArrayList<Mesurable> list = new ArrayList<Mesurable>();list.add(new Cercle(2,2,3)); // OK car mesurable ...list.add(new Rectangle(2,2,3,4)); // OK car mesurable ...// list.add(new Point(2,2)); // KO car non-mesurable ...System.out.println("Surface totale = "+calculeSurface(list));

}

En fait: Cercle et Rectangle sont (aussi) des sous-types de Mesurable

2) Hiérarchies séparées

Dans l'exemple précédent, Rectangle et Cercle ont une même super-classe (Figure)

... mais on peut bien sûr dépasser ce cadreSoit une classe B héritant de A (ex.: B=Rectangle, A=Figure)Soit une classe D héritant de C (ex.: D=Chambre, C=Piece)

Soit I une interfaceB implémente I (ex.: Rectangle implémente Mesurable)D implémente I (ex.: Chambre implémente Mesurable)

Compatibilités:B est compatible avec B, A et ID est compatible avec D, C et I

... donc les instance de B et D sont toutes deux utilisables avec le même type I (=> polymorphisme)

but: « Traverser » les hiérarchies séparées

Figure

+ translater(tx : double, ty : double) : void+ toString() : String

« abstract»

Polygone

+ getSurface() : double+ mettreEchelle(sx : double, sy : double)

« abstract»

Point

+ calculerDistance(Point P2) : double

Segment

+ getLongueur() : double

RectangleTriangle

Decoration

Dessert

- nom : String

# Dessert(String nom)+ getNom() : String+ decorer(Nappage nappage) : void+ « abstract » fabriquer() : void+ toString() : String

« abstract»

Patisserie

+ Patisserie(String nom)+ decorer(Decoration deco) : void+ fabriquer() : void

FruitNappage

« abstract

»

Gateau

+ Gateau(String nom)+ decorer(Fruit fruit) : void+ fabriquer() : void

Mousse

+ Mousse(String nom)+ decorer(Fruit fruit) : void+ fabriquer() : void

Mêmes capacités Interface

3) Suppléer l'héritage

« Coût » du lien d'héritage élevéon ne peut hériter que d'une super-classeRemarque: certains langage autorisent l'héritage multiple (ex. C++, Python)

pourquoi pas Java ? Problèmes sémantiqueconflits de signaturesdispatch dynamique implicite trop coûteuxhéritage « en diamant »

Mais de temps en temps (assez rarement en pratique)=> on veut modéliser:

C « EST UN » A et C « EST UN » B (aussi)ex.: Hydravion « EST UN » Bateau... et Hydravion « EST UN » Avion

Solution possible: interfaces

Classe abstraite VehiculeInterface IAvionInterface IBateauClasse concrète Hydravion

hérite de Vehicule (Hydravion « EST UN » Vehicule)implémente IAvion (Hydravion « EST UN » IAvion)implémente IBateau (Hydravion « EST UN » IBateau)

Limitation des interfaces: pas d'implémentationimpossible de factoriser du code commun à tous les bateaux et tous les avions (solution: cf. Design patterns) : uniquement des signatures de méthodes

Exemple: interfaces

public interface IAvion { public void voler();

}

public interface IBateau { public void naviguer();

}

public class Hydravion extends Vehicule implements IAvion, IBateau {

// Contrat minimal: doit implémenter// 1) les méthodes abstraites de Vehicule (s'il y en a)// 2) les méthodes déclarées dans l'interface IAvion// 3) les méthodes déclarées dans l'interface Ibateau

public void voler() { System.out.println("Je vole"); }public void naviguer() { System.out.println("Je navigue"); }// etc.

}

public interface IAvion { public void voler();

}

public interface IBateau { public void naviguer();

}

public class Hydravion extends Vehicule implements IAvion, IBateau {

// Contrat minimal: doit implémenter// 1) les méthodes abstraites de Vehicule (s'il y en a)// 2) les méthodes déclarées dans l'interface IAvion// 3) les méthodes déclarées dans l'interface Ibateau

public void voler() { System.out.println("Je vole"); }public void naviguer() { System.out.println("Je navigue"); }// etc.

}

Remarque: pas de limite sur le nombre d'interfaces implémentées

4) Cas particuliers

Interfaces Marqueursaucune méthode à implémentermais évoque une propriété commune

ex. interface Clonable => classe avec clone publiccf. cours 4

ex. interface Serializable => repr. externeetc.

Interfaces Standardsex. interface Comparablepour introduire un ordre entre instances d'une classeméthode public int compareTo(Object o)

cf. annales

Conclusion

Interfaces: outils d'abstractionUniquement des signatures de méthodes publiques(= type)Utile pour: polymorphisme, capacités partagées, etc.

Paquetages: outils de modularisationRassemblement de classes partageant un «objectif» communnouveaux points de vue:

héritier/paquetage: pour les sous-classes du même paquetage

top related