interface et classe ift1025, programmation 2 jian-yun nie

Post on 04-Apr-2015

110 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Interface et Classe

IFT1025, Programmation 2

Jian-Yun Nie

Concepts importants

• Interface: un contrat qu’une classe doit se conformer– Favorise la réutilisation des codes– Il suffit de savoir qu’une classe se conforme à une

interface pour pouvoir l’utiliser (sans connaître les détails de son implantation)

• Classe normale: une classe implantée (dont les méthodes sont toutes définies)

• Classe abstraite: une classe qui n’est pas complètement implantée– Mi-chemin entre classe normale et interface

Utilisation des classe

• Soit la classe BankAccount et les sous-classes CheckingAccount et SavingsAccount

• On peut faire des opérations en commun sur l’ensemble d’objets de la classe BankAccount (y compris ceux des sous-classe),

• Principe:– Pour tout objet ref de BankAccount:

• ref.operation– Conditions:

• operation est définie pour la classe mère (pour que ref.operation ne gégère pas une erreur de compilation)

• Operation est héritée ou redéfinie dans les sous-classes (polymorphisme)

• Polymorphisme assure qu’on utilise la version de l’instance

Exemple trivial: trouver balance maxpublic BankAccount maxAccount(BankAccount [] compte){

BankAccount ref, refMax;int i;double max = 0;for (i=0; i<compte.length; i++){

ref = compte[i];if (ref.getBalance() > max) {

max = ref.getBalance(); refMax=ref;

}}return refMax;

}

• C’est possible grâce à getBalance() dans la classe BankAccount (et héritée dans les sous-classes)

Utilisation:BankAcount meilleurClient;BankAccount [] clients = {new BankAccount(100), new CheckingAccount(10), //Petit tableau de 3 éléments

new SavingsAccount(0.05)}… // des manipulations sur ces comptesmeilleirClient = maxAccount(clients);

• Avantage de l’héritage et l’homogénéité dans une classe

Cas non trivial

• On ne peut pas implanter une méthode pour la classe mère, mais seulement dans les sous-classes

• Exemple:– Classe: Forme: draw() non implantables– Sous-classes: Rectangle: draw() implanté

Rond: draw() implantée

• Mais on veut quand même utiliser la référence ref de classe Forme pour ref.draw()

Généralisation

• On veut créer des opérations applicables pour toutes les instances d’une classe

• Si une méthode est implantée pour la classe mère et toutes les sous-classe (héritée ou redéfinie)– Cas trivial: la méthode est applicable

• Deux cas non triviaux:1. La méthode ne peut pas être implantée pour la

classe mère, mais elle le peut pour les sous-classes

2. On désire appeler la même méthode pour différentes classes (non reliées)

Premier cas: classe abstraite• On veut définir une classe correspondant un

concept (abstraite) englobant toutes les formes (rectangle, triangle, etc.)

• On sait que chaque forme a une surface• On souhaite définir une méthode getSurface

pour chaque forme • Problème:

– Il existe pas une façon générale pour calculer la surface pour une forme

– Le calcul est possible seulement pour les sous-classes (Rectangle, Triangle, Rond, etc.)

Hiérarchie

Forme: getSurface()

Rectangle Triangle Rond …

getSurface() getSurface() getSurface()

• On ne veut pas créer une instance de Forme• Solution: classe abstraite pour la classe mère

Non implantable

Deuxième cas

• On veut pouvoir appliquer une opération sur des objets– Ex: comparer les objets de la même classe pour

connaître un ordre: <, >, etc.

• Cette comparaison doit s’appliquer sur des classes très différentes– BankAccount, Rectangle, etc. avec des critères

différents

• Impossible d’utiliser classes abstraite pour ce cas– Les classe ne sont pas sous la même classe mère

Illustration

Object

BankAccount Mot Personne Forme

CheckingAccount Rectangle Triangle Rond

SavingsAccount

Classes pour lesquelles on veut définir l’ordre• Impossible de regrouper les classes sous une autre classe mère

– Héritage simple

• Solution: interface

Ordre

Classe abstraite

• Déclarationabstract public class Nom { … }

• Exempleabstract class Forme

{

int x, y; // coordonnée du début de la forme

abstract float getSurface();

}

Caractéristiques de classe abstraite

• Déclaration de classe avec abstract• Dans le corps {…}:

– On peut définir une méthode abstraite• abstract float getSurface();• Méthode abstraite n’a pas de corps (non implantée)

– Mais une classe abstraite peut ne pas avoir de méthode abstraite

– On peut déclarer des attributs et implanter des méthodes

• On ne peut pas créer d’instance d’une classe abstraite– new Forme(): Erreur de compilation

Sous-classes d’une classe abstraite

• class SousClasse extends Classe

• Si une sous-classe n’est pas abstraite– Toutes les méthodes abstraites héritées

doivent être implantées (avec un corps)– Sinon, la sous-classe doit aussi être abstraite

• Instance possible pour une sous-classe non abstraite

Exempleabstract class Forme

{int x, y; // coordonnée repère de la formeabstract float getSurface();abstract void draw();

}

public class Rectangle extends Forme{

int longueur, largeur;public float getSurface(){

return (float) longueur * largeur;}public void draw(){ … // dessiner le rectangle}

}

• Une sous-classe concrète doit implanter toutes les méthodes abstraites héritées

Exemple (cont.)public class Rond extends Forme{

int rayon;public float getSurface(){

…}

}

// Une forme composée de deux autres formesabstract class FormeComposee extends Forme{

Forme f1, f2;}

• Si une sous-classe n’implante pas toutes les méthodes abstraite, elle continue à être abstract

Hérités:int x, y; abstract float getSurface();abstract void draw();

Interface• Interface = contrat = exigence de certains types

de comportements• Exigences applicables sur des classes

différentes: BankAccount, Mot, …– Exemple: ordonner les objets

• BankAccount: selon la balance• Mot: selon l’ordre de mot, …

• Si on utilise seulement classe (abstraite):– On doit définir ces comportements séparément dans

chaque classe – Pas moyen de regrouper ces objets

Utilisation désirée (exemple)

• Pour un groupe d’objets avec un comportement commun: ordre(Objet)– Faire le même traitement de tri– Programme général qui fonctionne sur tous les objets

possédant ordre(Objet)• Pour tous ref1 et ref2 de ce type

– ref1.ordre(ref2) >0, ref1.ordre(ref2) =0, ref1.ordre(ref2) <0

– Réordonner selon leur comparaison

– Ce programme ne doit pas seulement fonctionner pour une classe

– Solution: interface

interface

• Une interface permet de regrouper les objets qui peuvent manifester le même type de comportement (mêmes méthodes)

• Interface n’a pas la même contrainte de héritage simple pour les classe– Une classe peut se conformer à plusieurs interfaces– Ex:

• Mot peut se comparer par ordre(…) et peut être mesuré en longueur, etc.

• Interface 1 pour ordre, interface 2 pour longueur, …

Définition d’une interface

• public interface Measurable

{

double getMeasure();

} • Lister toutes les méthodes (comportements)

désirées sans implantation (juste la signature)– Méthodes sont automatiquement abstract et public

• Pas d’attribut (sauf constante)

Utiliser une interface

• Une classe se conforme à une interface:– class BankAccount implements Measurable

{ …public double getMeasure() {

return value; }

• La classe doit implanter toutes les méthodes exigées par l’interface

Utiliser une interface

• Une autre classe peut se conformer à la même interface• public class Coin implements Measurable

{ public double getMeasure() {

return value; } . . .

} • Mécanisme similaire à un héritage multiple, mais

différent

Utiliser une interface• On peut utiliser une interface comme un type• Ex: déterminer le max et la somme:public class DataSet { . . .

public void add(Measurable x) {

sum = sum + x.getMeasure(); if (count == 0 || maximum.getMeasure() < x.getMeasure())

maximum = x; count++; } public Measurable getMaximum() {

return maximum; } private double sum; private Measurable maximum; private int count;

}

x est du type Measurable:- possède getMeasure()

Utiliser une interface• 01: /**• 02: This program tests the DataSet class.• 03: */• 04: public class DataSetTester• 05: {• 06: public static void main(String[] args)• 07: {• 08: DataSet bankData = new DataSet();• 09: • 10: bankData.add(new BankAccount(0));• 11: bankData.add(new BankAccount(10000));• 12: bankData.add(new BankAccount(2000));• 13: • 14: System.out.println("Average balance = " • 15: + bankData.getAverage());• 16: Measurable max = bankData.getMaximum();• 17: System.out.println("Highest balance = " • 18: + max.getMeasure());• 19: • 20: DataSet coinData = new DataSet();• 21: • 22: coinData.add(new Coin(0.25, "quarter"));• 23: coinData.add(new Coin(0.1, "dime"));• 24: coinData.add(new Coin(0.05, "nickel"));• 25: • 26: System.out.println("Average coin value = " • 27: + coinData.getAverage());• 28: max = coinData.getMaximum();• 29: System.out.println("Highest coin value = " • 30: + max.getMeasure());• 31: }• 32: }

Average balance = 4000.0 Highest balance = 10000.0 Average coin value = 0.13333333333333333 Highest coin value = 0.25

Relation entre classe et interface

class BankAccount implements Measuarable• Convertir le type d’une classe à une interface

– BankAccount account = new BankAccount(10000);Measurable x = account; // OK System.out.println(x.getMeasure());

• Casting une référence du type interface en une classe– Ajouter un objet à DataSet

DataSet coinData = new DataSet();coinData.add(new Coin(0.25, "quarter"));coinData.add(new Coin(0.1, "dime"));. . .Measurable max = coinData.getMaximum(); // Get the largest coin

– String name = max.getName(); // ERROR – Coin maxCoin = (Coin) max;

String name = maxCoin.getName(); // OK

Utilisation d’interface générale

• Interface comme un type abstrait de données– Liste– Arbre binaire– …

• Chaque type abstrait possède des méthodes « standard »

• Interface: exiger ces méthodes

Classe abstraite vs. Interface• Classe abstraite

– Certaines méthodes peuvent être abstraites– Peut contenir des attributs– Peut implanter des méthodes– Héritage simple

• Interface = contrat– Aucune implantation de méthode– Différentes classes peuvent signer le même contrat

• Classe = famille – posséder le même nom de famille– a la même habileté (peut être une méthode abstraite)

• Interface = contrat– Contrat commun pour différentes familles

Exemple: Interface Movable

Movable

Potion

«interface»

SwordRing

Gnomemoves

Interface Weapon

Weapon

Pen

«interface»

MissileLauncherSword

Explorerwields

“Héritage” Multiple d’interfaces par une classe

Weapon

«interface»

Sword

Movable

«interface»

class Sword implements Weapon, Movable {…}

Extension d’interface• Assume all weapons are movable:

Weapon

Pen

«interface»

MissleLauncherSword

Movable

Potion

«interface»

Ring

interface Weapon extends Movable {…}

Interface

Modifier une interface?

• Si une classe définie n’est plus suffisante– Ajouter des attributs et des méthodes– Les autres classes utilisant cette classe continuent à

fonctionner

• Si une interface n’est plus suffisante – Ne pas ajouter des méthodes abstraites– Sinon, les classe qui sont conformes à l’interface ne

le seront plus (très coûteux à modifier toutes ces classes!)

– On définit plutôt une sous-interface– interface SousInterface extends SuperInterface

Extension multiple d’interface

• Une interface peut extends plusieurs autres interfaces

DataInput

«interface»

DataOutput

«interface»

DataIO

«interface»

interface DataIO extends DataInput, DataOutput { }

instanceOf

• Tester si une instance est d’une classe (sous-classe)• Fonctionne aussi pour tester si une instance est du type

d’une interface (se conforme à une interface)• Exemple:

interface DataIO extends DataInput, DataOutput { }DataIO refInterface;BankAccount compte;

if (refInterface instanceOf DataOutput) …

if (compte instanceOf Movable) …

Utilisation d’interface et de classe

• Interface comme type de donnée – Partagent les méthodes

• Classe comme type de données – Partagent les méthodes et attributs

• Les deux peuvent se convertir– refInterface instance – refClasse instance– Casting:

• (Interface).refClasse: utile?– refClasse peut faire la même chose que (Interface).refClasse.

• (Classe).refInterface: utile!– Accéder à d’autres attributs et méthodes de la Classe

Exemple d’interface en Java

• Collection

Collectionpublic interface Collection<E> extends Iterable<E> { //Basic operations int size(); boolean isEmpty(); boolean contains(Object element); boolean add(E element); //optional boolean remove(Object element); //optional Iterator iterator(); //Bulk operations boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); //optional boolean removeAll(Collection<?> c); //optional boolean retainAll(Collection<?> c); //optional void clear(); //optional //Array operations Object[] toArray(); <T> T[] toArray(T[] a);}

<E>: Genetic

Traverser une collection (aperçu)

public interface Iterator<E> { boolean hasNext(); E next(); void remove(); //optional}

Utilisation:Supposons: boolean cond(Object)

static void filter(Collection c) { for (Iterator i = c.iterator(); i.hasNext(); ) if (!cond(i.next())) i.remove();}

Listpublic interface List<E> extends Collection<E> { //Positional access E get(int index); E set(int index, E element); //optional boolean add(E element); //optional void add(int index, E element); //optional E remove(int index); //optional abstract boolean addAll(int index, Collection<? extends E> c); //optional

//Search int indexOf(Object o); int lastIndexOf(Object o);

//Iteration ListIterator<E> listIterator(); ListIterator<E> listIterator(int index);

//Range-view List<E> subList(int from, int to);}

ArrayList

java.util Class ArrayList<E>

java.lang.Object java.util.AbstractCollection<E> java.util.AbstractList<E> java.util.ArrayList<E>

All Implemented Interfaces:

Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess

Hiérarchie des classes

Comparaison avec AbstractListpublic abstract class AbstractList<E>extends AbstractCollection<E>implements List<E>

{

// Méthodes implantées:

void add(int index, E element) {…}

void clear() {…}

int hashCode() …

}

Inner class: concept• Définir une classe qui a une utilité locale comme inner classs:• public class DataSetTester3

{ public static void main(String[] args) {

class RectangleMeasurer implements Measurer { . . . }

Measurer m = new RectangleMeasurer(); DataSet data = new DataSet(m);. . . }

} • Dans une inner class, on peut accéder aux méthodes et attributs de la

classe qui l’englobe (DataSetTesters)

top related