Classes abstraites et interfaces Interface et implémentation * Classe = interface + implémentation * Interface = signature de la classe * Partie visible * Fonctionnalités fournies par la classe * Signature des membres * Implémentation = fonctionnement de la classe * Partie cachée * Comportement interne de la classe * Corps / contenu des méthodes * Généralement: héritage ==> implémentation + interface Exemple d'héritage multiple Héritage multiple: problèmes ? * Java et C#: héritage multiple interdit * Héritage d'une seule classe autorisé ==> une seule implémentation héritée * Possibilité d'hériter plusieurs interfaces * C++: héritage multiple autorisé * Héritage de plusieurs classes autorisé ==> plusieurs implémentations et interfaces héritées * Pourquoi s'interdire l'héritage multiple d'implémentations ? * Héritage multiple = erreur de conception (souvent) * Agrégation mieux adaptée ==> mécanisme de "délégation" * Héritage multiple ==> conflits * Héritage de deux membres avec le même nom * Comment les distinguer ? * Héritage en "diamant": même classe héritée plusieurs fois * Conflits évités avec l'héritage virtuel (C++) Mécanisme de délégation * Principe * Agréger une fonctionnalité (plutôt que d'en hériter) * L'objet qui possède la fonctionnalité est le "délégué" * Toute requête est transmise au délégué Délégation: éviter l'héritage multiple Méthodes et classes abstraites * Méthode abstraite = méthode virtuelle sans implémentation * Son implémentation n'aurait aucun sens * Exemple: méthode "tracer" de la classe "Forme" * Classe abstraite = classe qui ne peut pas être instanciée * Son instanciation n'aurait aucun sens * Exemple: classe "Forme" * Possède souvent au moins une méthode abstraite * Peut définir des attributs * Syntaxe * Méthode abstraite * Java / C#: abstract void tracer(); * C++: virtual void tracer() = 0; * Classe abstraite * Java / C#: abstract class Forme * C++: automatique si au moins une méthode est abstraite Classes abstraites en Java * Classe abstraite "Forme" public abstract class Forme { protected int x1; protected int y1; public Forme(int a,int b) { x1 = a; y1 = b; } public abstract void tracer(java.awt.Graphics g); } * Classe concrète "Rectangle" héritant de "Forme" public class Rectangle extends Forme { protected int largeur; protected int hauteur; public Rectangle(int a,int b,int c,int d) { super(a,b); largeur = c; hauteur = d; } public void tracer(java.awt.Graphics g) { g.drawRect(x1,y1,largeur,hauteur); } } * Instanciation * new Forme(27,14) ==> erreur * new Rectangle(27,14,3,86) ==> ok Classes abstraites pures et interfaces * Classe abstraite vouée à être super-classe * Ne peut être instanciée * Nécessité de redéfinir les méthodes abstraites * Instances créées dans les classes dérivées * Classe abstraite pure ~ "interface" * N'a pas d'attributs * Ne possède que des méthodes abstraites * N'a qu'une interface, aucune implémentation * Possibilité de définir explicitement une interface (Java / C#) * Se manipule comme une classe * Mais n'a pas d'implémentation * A hérite interface B = A "implémente" interface B Interfaces: éviter l'héritage multiple Interfaces en Java (1/2) * Déclaration d'une interface * Mot-clé "interface" * Pas de code, toutes les méthodes sont abstraites * Le mot-clé "abstract" n'est pas nécessaire * Pas d'attributs * Constantes autorisées * Exemple public interface ComposantGraphique { ... public void tracer(java.awt.Graphics g); ... } * Héritage d'une interface * Mot-clé "implements" * Héritage entre interfaces possible: interface A implements B * Héritage multiple d'interfaces possible: class A implements B,C Interfaces en Java (2/2) * Héritage ==> implémentation de l'interface * Implémenter toutes les méthodes abstraites * Sinon, pas d'instanciation possible * Une interface a le même rôle qu'une classe * Interface = type * Mécanisme de polymorphisme dynamique * Exemple public class Ligne extends Forme implements ComposantGraphique { protected int x2; protected int y2; public Ligne(int a,int b,int c,int d) { super(a,b); x2 = c; y2 = d; } public void tracer(java.awt.Graphics g) { g.drawLine(x1,y1,x2,y2); } } |