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

C# Discussion :

covariance et interfaces


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Novembre 2005
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 24
    Par défaut covariance et interfaces
    salut.
    je suis désolé si cette question a été posée, j'ai cherché dans la FAQ C# sans succès.

    j'ai une interface IMessage qui représente un message à envoyer:

    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
     
    public interface IMessage
    {
    string Corps {get; set;}
     
    string Sujet {get; set;}
     
    string Expediteur {get; set;}
     
    ICollection<string> Destinataires {get; set;}
     
    void Composer();
     
    void Concatener(Icollection<IMessage> messages);
    }
    La classe Email implémente IMessage:

    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
     
    public class Email : IMessage
    {
    public string Corps {/* Ici des get et set sur le champ privé */}
     
    public string Sujet {/* Ici des get et set sur le champ privé */}
     
    public string Expediteur {/* Ici des get et set sur le champ privé */}
     
    public ICollection<string> Destinataires {/* Ici des get et set sur le champ privé */}
     
    public MailMessage LeMail;
     
    public void Composer() {/* crée un objet MailMessage et l'attache à LeMail */}
     
    public void Concatener(ICollection<Email>) {/* concatene les corps de monEmail1+monEmail2+this */}
     
    //tous les champs privés ici...
    }
    Le problème: le compilo râle parce que dans l'interface Concatener() prend en argument une ICollection<IMessage> alors que l'implémentation prend une ICollection<Email>.

    Pourtant Email est bien une implémentation de IMessage.

    Je pourrais implémenter Concatener() comme prenant en argument une ICollection<IMessage> mais alors comment empêcher un client de concaténer des Emails et des Sms, comme dans:
    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
     
    Sms sms1 = new Sms();
     
    Sms sms2 = new Sms();
     
    ICollection<IMessage> smss = new List<Sms>(2);
     
    smss.Add(sms1);
     
    smss.Add(sms2);
     
    Email unEmail = new Email();
     
    unEmail.Concatener(smss); //Sms implémente IMessage !
     
    //...
    J'aimerais imposer la condition suivante sur les implémentations de IMessage:
    chaque objet ne peut concaténer que des objets du même type.

    (Je suis pas sur que le code ci-desssus compile mais c'est l'idée).
    Merci !

  2. #2
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 273
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 273
    Par défaut
    Ce dont tu as besoin s'appelle un design pattern adapteur;

    Bref tu as besoin d'adapter la concaténation en fonction du type de message
    --> mail avec mail
    --> sms avec sms

    C'est ici

    Et en plus perso, je le trouve très très bien ce tuto !

  3. #3
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 273
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 273
    Par défaut
    sinon, tant que j'y pense, tu peux aussi faire ça :
    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
     
     
    namespace Bidules
    {
        namespace ClassSupport
        {
            public interface IMessage
            {
                string Corps { get; set; }
                string Sujet { get; set; }
                string Expediteur { get; set; }
                ICollection<string> Destinataires { get; set; }
                void Composer();
                void Concatener<T>(ICollection<T> messages);
            }
     
            public abstract class AbstractMessage<T> : IMessage
            {
     
                #region IMessage Members
     
                public string Corps
                {
                    get
                    {
                        throw new NotImplementedException();
                    }
                    set
                    {
                        throw new NotImplementedException();
                    }
                }
     
                public string Sujet
                {
                    get
                    {
                        throw new NotImplementedException();
                    }
                    set
                    {
                        throw new NotImplementedException();
                    }
                }
     
                public string Expediteur
                {
                    get
                    {
                        throw new NotImplementedException();
                    }
                    set
                    {
                        throw new NotImplementedException();
                    }
                }
     
                public ICollection<string> Destinataires
                {
                    get
                    {
                        throw new NotImplementedException();
                    }
                    set
                    {
                        throw new NotImplementedException();
                    }
                }
     
                public void Composer()
                {
                    throw new NotImplementedException();
                }
     
                public virtual void Concatener<T>(ICollection<T> messages)
                {
                    throw new NotImplementedException();
                }
     
     
                #endregion
            }
     
            public class Email:AbstractMessage<Email>
            {
                public override void Concatener<Email>(ICollection<Email> messages)
                {
                    base.Concatener<Email>(messages);
                }
            }
            public class Sms : AbstractMessage<Sms>
            {
                public override void Concatener<Sms>(ICollection<Sms> messages)
                {
                    base.Concatener<Sms>(messages);
                }
            }
     
            public class howto
            {
                static void main()
                {
                    Sms sms=new Sms();
                    sms.Concatener(new Collection<Sms>());
     
                    Email mail=new Email();
                    mail.Concatener(new Collection<Email>());
     
                }
            }
     
        }
    }
    Tu as toujours le bénéfice de l'interface, et surtout tu peux t'appuyer sur des génériques plutôt que de la réflexion pour gérer la dissociation.

  4. #4
    Membre averti
    Inscrit en
    Novembre 2005
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 24
    Par défaut
    Citation Envoyé par B.AF Voir le message
    Ce dont tu as besoin s'appelle un design pattern adapteur...
    sinon, tant que j'y pense, tu peux aussi faire ça :...
    ok merci pour ces 2 bonnes idées.
    petites remarques:
    - pour le design pattern:
    c'est bien mais j'espérais que la solution serait moins compliquée. Le fait d'encapsuler mon Email dans un autre objet ça me fait mal vu que j'avais fait exprès une interface pour que toutes les classes du genre Email, Sms etc... soient manipulables de la même façon...c'est embêtant de devoir réencapsuler tous mes trucs...vu que c'est moi qui définit les classes et les interfaces je devrais bien pouvoir m'en sortir autrement...
    - pour les génériques:
    là y a la totale: interface+classe abstraite+génériques ! c'est bien mais c'est vraiment la grosse artillerie. mais c'est pas bête...

    en fait je croyais bêtement que je pouvais m'en sortir avec du polymorphisme...merci pour les idées.

  5. #5
    Membre averti
    Inscrit en
    Novembre 2005
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 24
    Par défaut
    après avoir réfléchi je me rends compte que c'est normal que le compilo se plaigne: mon contrat stipule que Concatener() prend une ICollection<IMessage> comme argument mais ma fonction réelle exige une ICollection<Email>...ie je dis au client: "passe moi ce que tu veux du moment que ça implémente IMessage" mais dès qu'il veut appeler ma méthode je lui dis "ah non désolé je prends que des Email"...
    l'argument de l'implémentation devrait être plus général que celui de l'interface, pas moins.
    comment c'est déjà ? ah ouais

  6. #6
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 273
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 273
    Par défaut
    Oui c'est pour ça que je te dis :

    Soit tu as besoin d'adapter
    Soit tu as besoin de spécifier quel type reçoit ta collection

  7. #7
    Membre Expert Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Problème classique, vieux comme le C++

    Avec une chtite contrainte (clause where),c e genre de problème se résoud très bien. Remplace
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void Concatener(Icollection<IMessage> messages);
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void Concatener<U>(Icollection<U> messages) where U : IMessage;
    La prochaine version de C# (4) gèrera la covariance, en attendant on se débrouille.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VB6] [Interface] ComboBox à plusieurs colonnes
    Par mtl dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 30/03/2004, 17h35
  2. [VB6] [Interface] Horloge 7 segments
    Par selenay dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 07/10/2002, 16h15
  3. interface utilisateur avec OpenGL
    Par demis20 dans le forum OpenGL
    Réponses: 6
    Dernier message: 03/10/2002, 12h27
  4. [VB6] [Interface] Tester le Type de Controle
    Par SpaceFrog dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 16/09/2002, 09h51
  5. [VB6] [Interface] Icones de boutons de barre d'outils
    Par elifqaoui dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 13/09/2002, 15h50

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