IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

interet des interfaces ?


Sujet :

Langage Java

  1. #1
    Membre habitué
    Inscrit en
    Mai 2006
    Messages
    525
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 525
    Points : 150
    Points
    150
    Par défaut interet des interfaces ?
    Je voulais savoir d'après vous c'est quoi exactement l'interet des interfaces en java, car perso, je trouve qu'elles sont inutiles, pourquoi ne pas implémenter directement dans les classes concretes sans passer par des interfaces???

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    361
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 361
    Points : 429
    Points
    429
    Par défaut
    Et l'intérêt de la fonction recherche ? Inutile aussi ?

  3. #3
    Membre averti
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    321
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 321
    Points : 360
    Points
    360
    Par défaut
    Je crois que ta question risque de provoquer des arrets cardiaques à pas mal de personne ici . Une interface permet de décrire un comprotement particulier. C'est un moyen de typer les objets par leur competences (les méthodes qu'ils savent executer) plutot que par leur classe.
    De plus, utiliser des interfaces te permet d'introduire beaucoup de souplesses dans le developpement de ton application. Imagine que pour un algorithme tu necessite de calculer la distance entre deux points (algorithme A* par exemple). Il existe différent types de distances (euclidienne, de Manhattan, diagonale ...). Si tu veux que ton application soit modulaire, tu as tout interet a manipuler une interface qui contient une methode calculerDistance plutot qu'une implementation directement. Je te conseille un ouvrage interessant qui aborde notamment ce sujet et plus generalement la "bonne" facon de concevoir une appli orientée objet : "design patten : la tete la premiere" chez oreilly

  4. #4
    Membre habitué
    Inscrit en
    Mai 2006
    Messages
    525
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 525
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par nicØB
    Et l'intérêt de la fonction recherche ? Inutile aussi ?
    c'est quoi le rapport ? pour toi c quoi l'interet ?

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    63
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 63
    Points : 77
    Points
    77
    Par défaut
    Il n'y a pas possibilité d'héritage multiple en java, donc on passe par les interfaces. Par exemple, il suffit de regarder dans l'api standard. Si tu prends l'interface List, il y a plusieurs classes qui implémente cette interface, de leur propre manière. Et si tu dois manipuler des lists de toute sorte, tu n'aura qu'à manipuler l'interface.

    Les interfaces sont utilisées dans les pattern de type Factory ou pour l'injection de dépendance.

    Les interfaces sont des contrats que les classes qui les implémentent doivent respecter, même si le développeur peut les implémenter comme il veut. Il manque peut-être un mécanisme de contrôle type programmation par contrats.

  6. #6
    Membre expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Points : 3 675
    Points
    3 675
    Par défaut
    Une interface permet beaucoup!!

    Une interface, c'est un contrat: une classe qui implémente "Comparable" permet de comparer plusieurs instances de cette classes entre elles afin de définir laquelle est supérieure ou inférieure.

    Implémenter une interface, ça revient à déclarer "cette classe est capable de faire ceci".

    C'est en utilisant les interfaces que l'on peut "simuler" un héritage multiple (la terminologie que j'emploie n'est pas tout à fait exacte): une classe peut implémenter Comparable, Cloneable, Iterable, et plein d'autres interfaces. Cela permet de "greffer" des fonctionnalités sur des classes.

    Cela permet aussi d'utiliser des classes sans se préoccuper de leur type réel et de leur implémentation, afin de pouvoir tout modifier plus facilement par la suite.

    L'exemple typique des listes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ArrayList a = new ArrayList(); // Mauvais, car "ArrayList" est référencé directement, alors qu'il ne s'agit que d'une implémentation de Collection
     
    Collection c = new ArrayList(); // Bon, car on peut facilement modifier "new ArrayList()" par "new HashTable()" ou "new TreeSet()", sans que cela modifie le reste du programme

    Les interfaces sont sans doute l'une des meilleure trouvail de Java!


    "Le plug gros problème des citations trouvées sur internet, c'est qu'on ne peut jamais garantir leur authenticité"

    Confucius, 448 av. J-C

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    239
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 239
    Points : 239
    Points
    239
    Par défaut
    Une interface decrit le contrat que doit respecter une implementation. Exemple concret :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public interface Moteur {
     
       void demarrer();
     
       void arreter();
     
       void pause();
    }
    Si tu prends le moteur Essence ou Diesel, la classe devra respecter (implementer) au MINIMUM ces 3 méthodes. Bien-sûr le corps des méthodes est completement libre (le demarrage d'un moteur essence ne se faisant pas de la même manière qu'un moteur essence).

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 44
    Points : 50
    Points
    50
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public abstract class Moteur {
     
       public abstract void demarrer();
     
       public abstract void arreter();
     
       public abstract void pause();
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public class MoteurEssence extends Moteur {
     
    }
    Dans certains cas je préfère un abstract. J'ai parfois du mal à choisir entre interface et classe abstraite. L'avantage d'une interface c'est qu'une classe peut hériter de plusieurs interface alors qu'une classe ne peut étendre qu'une seule classe abstraite ...

    Tout dépend du contexte ...

    Citation Envoyé par sleepy2002
    Une interface decrit le contrat que doit respecter une implementation. Exemple concret :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public interface Moteur {
     
       void demarrer();
     
       void arreter();
     
       void pause();
    }
    Si tu prends le moteur Essence ou Diesel, la classe devra respecter (implementer) au MINIMUM ces 3 méthodes. Bien-sûr le corps des méthodes est completement libre (le demarrage d'un moteur essence ne se faisant pas de la même manière qu'un moteur essence).

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    361
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 361
    Points : 429
    Points
    429
    Par défaut
    Citation Envoyé par gloglo
    c'est quoi le rapport ? pour toi c quoi l'interet ?
    Ce n'est pas la première fois que quelqu'un pose cette question.


    Un autre intérêt pour ma part c'est lorsque l'on utilise Spring (ou autre lib permettant de faire de l'injection de dépendances).
    Celon le contexte, on charge l'implémentation que l'on veut.

  10. #10
    Membre confirmé Avatar de julien-blaise
    Homme Profil pro
    Développeur Java et C#
    Inscrit en
    Mai 2005
    Messages
    458
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur Java et C#

    Informations forums :
    Inscription : Mai 2005
    Messages : 458
    Points : 620
    Points
    620
    Par défaut
    Citation Envoyé par pgervaise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public abstract class Moteur {
     
       public abstract void demarrer();
     
       public abstract void arreter();
     
       public abstract void pause();
    }
    dans ce cas je ne vois pas l'utilité de la classe abstraite étant donné que tu ne définie aucune méthode. Une interface serait donc mieux adapté.

    L'avantage d'une interface c'est quand tu veux un type générique sans avoir à te préoccuper de la manière dont seront réaliser les choses.
    Suppose qu'on te demande de faire une application chargé de gérer l'envoie de message à des personnes d'un listing. Sauf que les moyens d'expédition du message sont différents. Certaine personnes le voudraont par mail, d'autres par courrier, d'autre par mail (et j'en passe).
    Sans interface, tu te retrouve à faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Sms.envoie(message); ou Mail.envoie(message); ou Courrier.envoie(message)
    avec toute les déclarations et définitions qui vont avec (soit trois objets minimum).
    Avec l'interface tu pourrais faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Envoyeur.envoie(message)
    avec seulement Envoyeur qui définit Sms, Mail ou Courier en fonction du clients.
    Demain, on invente un nouveau moyen de communication (holovision par exemple). Dans le premier cas tu dois tout refaire pour ce nouveau moyen, dans le second tu implément Envoyeur tu ajoute une condition et c'est fini.

    Je me suis un peu laisser aller désolé
    "La violence est le dernier refuge de l'incompétence" Salvor Hardin, Fondation

  11. #11
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 021
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 021
    Points : 1 047
    Points
    1 047
    Par défaut
    Bonjour à toutes et à tous,

    Sans vouloir polémiquer, mais pour avoir les idées plus claires sur la différence entre classe abstraite et interface, quelqu'un pourrait-il écrire un petit programme basé sur l'exemple précédent (des destinataires, des moyens d'expédition) en utilisant d'un côté des classes abstraites et de l'autre des interfaces.

    Pour moi :

    • avec des interfaces : il faut créer autant d'interfaces qu'il y a de moyens d'expédition, puis créer une classe implémentant toutes ces interfaces. Si on ajoute un moyen d'expédition, il faut créer une nouvelle interface, l'implémenter dans la classe utilisatrice et faire un nouveau "switch" dans cette classe.
    • avec des classes abstraites, il faut créer autant de classes à partir de la classe abstraite qu'il y a de moyens d'expédition, puis une classe qui exploite chacune des classes précédemment créées. Si on ajoute un moyen d'expédition, il faut créer une nouvelle classe issue de la classe abstraite et ajouter un "switch" dans la classe utilisatrice.

    Voilà ce que j'ai compris, mais je suis peut-être complètement à côté de la plaque. C'est pourquoi un petit programme valant mieux que de longs discours ...

    Au niveau applicatif, le listing comprend bien des couples "destinataire/moyen d'expédition" qui vont exploiter les ressources définies ci-dessus.

    Merci de votre aide.

    Pierre.

  12. #12
    Membre expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Points : 3 675
    Points
    3 675
    Par défaut
    Hello,

    il n'y a pas vraiment de solution purement "interface" ou purement "classe abstraite"

    La meilleure logique serait de partir d'une interface, de l'implémenter dans une classe abstraite, puis de définir des classes concrètes à partir de la classe abstraite.

    De toute façon, au final, le code doit se trouver dans des classes... L'utilisation d'interfaces ne fait que modifier le type de référence.

    Une implémentation de l'exemple ci-dessus pourrait être comme cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
     
    // Déclare l'interface d'un envoyeur
    interface Sender {
      void setRecipient(String s);
      void send(String msg);
    }
     
     
    // Ici, je défini l'implémentation standard de tous les "Sender", par ex. "setRecipient(String)" qui permet d'affecter un destinataire
    // Les classes abstraites contiennent généralement des implémentations standards pouvant être modifiés par les sous-classes
    abstract class AbstractSender implements Sender {
      protected String recipient;
      public void setRecipient(String s) {recipient = s;}
     
      public void toString(){
        return "Sender de classe "+getClass().getSimpleName();
      }
    }
     
     
    // Maintenant, je passe aux implémentations concrète
    class SMSSender extends AbstractSender {
      public void send(String msg){
        System.out.println("Envoi de "+msg+" par sms à "+recipient);
      }
    }
    class MailSender extends AbstractSender {
      public void send(String msg){
        System.out.println("Envoi de "+msg+" par mail à "+recipient);
      }
    }
    class PigeonVoyageurSender extends AbstractSender {
      public void send(String msg){
        System.out.println("Envoi de "+msg+" par pigeon voyageur à "+recipient+"!");
      }
    }
     
     
    // Une "main" pour tester
    public static void main(String[] arg){
      Sender s = new MailSender(); System.out.println(s);
      s.setRecipient("toto@toto.com");
      s.send("Ceci est le message 1");
     
      s = new PigeonVoyageurSender(); System.out.println(s);
      s.setRecipient("E32.3N45.5");
      s.send("Ceci est le message 2");  
    }
    "Le plug gros problème des citations trouvées sur internet, c'est qu'on ne peut jamais garantir leur authenticité"

    Confucius, 448 av. J-C

  13. #13
    Membre confirmé Avatar de julien-blaise
    Homme Profil pro
    Développeur Java et C#
    Inscrit en
    Mai 2005
    Messages
    458
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur Java et C#

    Informations forums :
    Inscription : Mai 2005
    Messages : 458
    Points : 620
    Points
    620
    Par défaut
    Vu que j'y ai passé un peu de temps voici la version executable en interface, par contre je n'ai pas pensé au puigeon voyageur.
    Faudra attendre un peu pour la version classe Abstraite.
    Fichiers attachés Fichiers attachés
    "La violence est le dernier refuge de l'incompétence" Salvor Hardin, Fondation

  14. #14
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 021
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 021
    Points : 1 047
    Points
    1 047
    Par défaut
    Avant toute chose, "Pill_S" et"julien-blaise", je vous remercie pour les morceaux de code que vous avez établis.
    Citation Envoyé par Pill_S
    ...il n'y a pas vraiment de solution purement "interface" ou purement "classe abstraite"
    Je me suis permis de modifier le code que tu m'as proposé en supprimant l'interface et en réintégrant la méthode "send" dans la classe abstraite "AbstractSender" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    /*
     * Main.java
     *
     * Created on 31 mai 2007, 14:36
     *
     * To change this template, choose Tools | Template Manager
     * and open the template in the editor.
     */
     
    package essai01;
     
    // D�clare l'interface d'un envoyeur
    /*interface Sender {
        void setRecipient(String s);
        void send(String msg);
    }*/
     
     
    // Ici, je d�fini l'impl�mentation standard de tous les "Sender", par ex. "setRecipient(String)" qui permet d'affecter un destinataire
    // Les classes abstraites contiennent g�n�ralement des impl�mentations standards pouvant �tre modifi�s par les sous-classes
    abstract class AbstractSender /*implements Sender*/ {
        protected String recipient;
        public void setRecipient(String s) {recipient = s;}
     
    /*    public void toString(){
            return "Sender de classe "+getClass().getSimpleName();
        }*/
        public void send(String msg) {
     
        };
    }
     
     
    // Maintenant, je passe aux impl�mentations concr�te
    class SMSSender extends AbstractSender {
        public void send(String msg){
            System.out.println("Envoi de "+msg+" par sms � "+recipient);
        }
    }
    class MailSender extends AbstractSender {
        public void send(String msg){
            System.out.println("Envoi de "+msg+" par mail � "+recipient);
        }
    }
    class PigeonVoyageurSender extends AbstractSender {
        public void send(String msg){
            System.out.println("Envoi de "+msg+" par pigeon voyageur � "+recipient+"!");
        }
    }
     
    /**
     *
     * @author Pierre
     */
    public class Main {
     
        /** Creates a new instance of Main */
        public Main() {
        }
     
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            // TODO code application logic here
            AbstractSender s = new MailSender(); System.out.println(s);
            s.setRecipient("toto@toto.com");
            s.send("Ceci est le message 1");
     
            s = new PigeonVoyageurSender(); System.out.println(s);
            s.setRecipient("E32.3N45.5");
            s.send("Ceci est le message 2");
        }
     
    }
    au final, le fonctionnement est le même.

    Donc, dans ce cas précis, je ne vois pas l'intérêt des interfaces.

    J'ai lu aussi la proposition qu'a faite "julien-blaise". Je n'y ai pas essayé de modification, mais il me semble que le principe est le même et que je peux y faire les mêmes actions.

    A mon sens, (mais là, je me fais l'avocat du diable ... ne me frappez pas !) les "interfaces" ont été mises en place pour réintroduire l'héritage multiple qui n'était pas supporté au départ. Mais bon, je me trompe peut-être totalement.

    Cordialement.

    Pierre

  15. #15
    Membre confirmé Avatar de julien-blaise
    Homme Profil pro
    Développeur Java et C#
    Inscrit en
    Mai 2005
    Messages
    458
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur Java et C#

    Informations forums :
    Inscription : Mai 2005
    Messages : 458
    Points : 620
    Points
    620
    Par défaut
    C'est déjà pas mal de réintroduire l'héritage multiple même si il ne s'agit que de ça.
    D'ailleurs attends que je te fasse la version classe abstraite, tu va voir la différence pour le coup
    "La violence est le dernier refuge de l'incompétence" Salvor Hardin, Fondation

  16. #16
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 021
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 021
    Points : 1 047
    Points
    1 047
    Par défaut
    Je n'ai jamais dit le contraire. Et en y pensant, je m'aperçois que si on a un modèle à faire, autant en faire une interface qu'une classe abstraite car, sait-on jamais, on pourra la réutiliser en héritage multiple , si cela se présente..

    Cordialement.

    Pierre

  17. #17
    Membre actif
    Avatar de bobuse
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    232
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 232
    Points : 278
    Points
    278
    Par défaut
    Imaginez ce qu'aurait donner l'utilisation du framework des listeners dans swing sans utiliser des interface.

  18. #18
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 109
    Points : 122
    Points
    122
    Par défaut
    Mes 0.2€...

    Comme il a déjà été dit, une interface est... une interface. C'est à dire ce que les clients de l'objet ont besoin de connaître pour pouvoir manipuler cet objet.

    Concrètement, si tu veux conduire une voiture, tu as beson de connaitre le tableau de bord (volant, pédale, etc...) c'est à dire son "interface de pliotage". Après, il peut y avoir un moteur essence, diésel ou à vapeur, de ton point de vue de conducteur ça n'est pas important. De plus si l'interface de pilotage est la même, tu est également capable de conduire un hors bord, par exemple.

    C'est ce concept qui est transcrit dans les interfaces java.

    Tu peux très certainement t'en passer si ça te fait plaisir. Néanmoins qu'est ce qui est conceptuellement le plus juste ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    class Voiture implements ITableauDeBord {}
    class HordBord implements ITableauDeBord {}
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    class Voiture extends AbstractTableauDeBord {}
    class HorsBord extends AbstractTableauDeBord {}
    Le second cas signifie que Voiture et HorsBord sont des sortes particulières de TableauDeBord...

    Enfin il est parfois désirable de ne pas être obligé d'induire un couplage avec une seule et unique superclasse. Imagine que toutes les connections de base de données du monde dussent hériter de java.sql.AbstractConnection et que lors d'une mise à jour du JRE un codeur mal réveillé de Sun y introduise un bug bloquant !

  19. #19
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par ChPr
    Donc, dans ce cas précis, je ne vois pas l'intérêt des interfaces.
    Citation Envoyé par ChPr
    A mon sens, (mais là, je me fais l'avocat du diable ... ne me frappez pas !) les "interfaces" ont été mises en place pour réintroduire l'héritage multiple qui n'était pas supporté au départ. Mais bon, je me trompe peut-être totalement.
    C'est tout à fait cela ! Toutefois j'ajouterais que si l'héritage multiple n'est pas supporté, c'est totalement volontaire. En effet ce dernier peut être amené à posé plus de problème qu'autre chose, en particulier lorsqu'on utilise majoritairement des méthodes virtuelles (c-a-d qui peuvent être redéfini dans les classes filles, et donc le comportement par défaut de Java).


    Comme cela a été dit, les interfaces font plus état de contrat qu'autre chose. Et il ne faut pas les mettres en concurrence avec les classes abstraites qui ont un rôle assez différent : proposer une implémentation de base. Généralement on ne fait pas un choix entre interface et classe abstraite : on fait les deux.



    En effet quel est le défaut de la version avec seulement des classes abtraites : il faut en hériter.
    Et cela peut poser problème, un exemple : Imaginons que j'ai une classe j'ai une classe Developpez qui gère la session HTTP avec le forum (et l'authentification), et une classe fille MPSender permettant d'envoyer des messages privé sur le forum :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class MPSender extends Developpez {
     
     
    	public void mp(String user, String message) {
    		System.out.println("Envoi d'un MP "+message+" a "+recipient+"!");
    	}
    }
    Je voudrais donner à cette classe le comportement de AbstractSender mais c'est impossible à cause de l'héritage multiple interdit....
    Il me faudrait donc faire une nouvelle classe qui hérite d'AbstractSender et qui comporte une classe MPSender qui se chargera de l'envoi... Pas top


    Avec une interface Sender il aurait suffit de faire implémenter l'interface et ses méthodes directement par la classe MPSender





    Donc le mieux serait d'utiliser les deux à la fois : interface et classe abstraite (on peut même dire les trois avec les implémentations) :
    1. L'interface permet de définir le comportement général.
    2. La (les?) classe abstraite propose une implémentation de base (généralement incomplète), en impélmentant certaines méthodes basiques et/ou générale, mais également en proposant d'autre méthode utilise aux classes filles ou en apportant d'autre comportement (la gestion de Listener par exemple).
    3. Enfin, les implémentations héritent de la classe abtraite et la complète en implémentant les méthodes abstraites (voir d'autres) selon les besoins...






    Voici donc comment j'aurai implémenté cela :


    1. L'interface se contente de décrire le contrat et les méthodes (sans oublier la javadoc que je n'ai pas mis ici ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    interface Sender {
    	public void setRecipient(String s);
    	public void send(String msg);
    }
    2. La classe abstraite implémente seulement la méthode setRecipient(). La méthode send() reste abstraite et devra être implémenté par les classes filles. Cette classe en profite également pour proposer une méthode getRecipient(), une redéfinition de toString() qui affiche le nom de la calsse et le destinataire, et propose enfin une gestion d'évenement lors des mdoifications des propriétées via les PropertyChangeListener :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    abstract class AbstractSender implements Sender {
     
        protected String recipient;
     
        // A ce niveaux, pas d'implémentation pour la méthode send()
        public abstract void send(String msg);
     
        // On implémente setRecipient() avec une gestion des listeners
        public void setRecipient(String s) {
        	firePropertyChangeEvent("recipient", recipient, s);
        	recipient = s;
        }
     
        // On implémente une méthode utilitaire supplémentaire :
        public String getRecipient() {
        	return recipient;
        }
     
        // On redéfinit certaine méthode hérité de Object
        @Override
        public String toString() {
        	return getClass().getSimpleName() + ":" + this.recipient;
        }
     
        // Et tout le neccessaire à la gestion des Listeners
        protected EventListenerList eventListenerList = new EventListenerList();
     
        public void addPropertyChangeListener(PropertyChangeListener listener) {
        	this.eventListenerList.add(PropertyChangeListener.class, listener);
        }
     
        public void removePropertyChangeListener(PropertyChangeListener listener) {
        	this.eventListenerList.remove(PropertyChangeListener.class, listener);
        }
     
        protected void firePropertyChangeEvent(String name, Object oldValue, Object newValue) {
        	final PropertyChangeEvent evt = new PropertyChangeEvent(this, name, oldValue, newValue);
        	for (PropertyChangeListener listener :
        		this.eventListenerList.getListeners(PropertyChangeListener.class)) {
        			listener.propertyChange(evt);
        	}
        }
     
    }

    3. Les implémentations de base sont identique aux votres (mais possèdent la gestion des listener et un 'joli' toString() ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class SMSSender extends AbstractSender {
        public void send(String msg){
            System.out.println("Envoi de "+msg+" par sms a "+recipient);
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class MailSender extends AbstractSender {
        public void send(String msg){
            System.out.println("Envoi de "+msg+" par mail a "+recipient);
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class PigeonVoyageurSender extends AbstractSender {
        public void send(String msg){
            System.out.println("Envoi de "+msg+" par pigeon voyageur a "+recipient+"!");
        }
    }

    Cette solution me permet à la fois d'avoir une interface qui me laisse totalement libre de l'implémentation, et une classe abstraite qui me propose une base commune


    Ainsi, ma classe MPSender serait devenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    class MPSender extends Developpez implements Sender {
     
     
    	public void mp(String user, String message) {
    		System.out.println("Envoi d'un MP "+message+" a "+recipient+"!");
    	}
     
     
    	protected String recipient;
     
    	public void setRecipient(String s) {
    		this.recipient = s;
    	}
     
    	public void send(String msg) {
    		// Appel de la méthode mp :
    		mp(this.recipient, msg);
    	}
     
    }

    Bien sûr il faut ensuire utiliser l'abstraction des implémentations, c'est à dire qu'on ne devrait pas utiliser les types AbstractSender ou les implémentations mais l'interface tant que c'est possible, c'est à dire qu'il NE FAUT PAS FAIRE :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PigeonVoyageurSender s = new PigeonVoyageurSender();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public void setSender(AbstractSender sender) { 
    	// ...
    }
    Mais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Sender s = new PigeonVoyageurSender();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public void setSender(Sender sender) { 
    	// ...
    }



    Cette solution à trois niveaux est la meilleure à mon avis, d'ailleurs on la retrouve souvent dans l'API

    • List -> AbstractList -> ArrayList, LinkedList
    • Set -> AbstractSet -> HashSet, TreeSet
    • Map -> AbstractMap -> HashMap, TreeMap
    • TableModel -> AbstractTableModel -> DefaultTableModel
    • etc.



    a++

    PS : j'ai encore fait un pavé... désolé

  20. #20
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 021
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 021
    Points : 1 047
    Points
    1 047
    Par défaut
    Même si ce sont des pavés, ce sont des explications claires et très bien argumentées ; et je vous en remercie.

    Je vais maintenant essayer de digérer ces concepts (désolé, j'ai programmé 10 ans en objet DELPHI sans interface).

    Cordialement.

    Pierre

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. interet des interfaces dans une architecture n-tiers
    Par anouar204 dans le forum Architecture
    Réponses: 1
    Dernier message: 28/01/2010, 20h14
  2. [PHP5] Atouts des interfaces ?
    Par Anomen dans le forum Langage
    Réponses: 5
    Dernier message: 15/01/2006, 13h50
  3. [MFC] accelerer la fab des interfaces
    Par giova_fr dans le forum MFC
    Réponses: 1
    Dernier message: 30/12/2005, 01h07
  4. Outil pour créer des interfaces graphiques
    Par Cyborg289 dans le forum Interfaces Graphiques en Java
    Réponses: 10
    Dernier message: 11/07/2005, 17h48
  5. [Logiciel]Cherche graphisme pour des interfaces visuelles
    Par smyley dans le forum Autres Logiciels
    Réponses: 9
    Dernier message: 14/11/2004, 03h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo