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 :

[C#] Information sur héritage et polymorphisme


Sujet :

C#

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    801
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 801
    Par défaut [C#] Information sur héritage et polymorphisme
    Bonjour,
    Voilà mon problème.
    Je voudrais créer une classe profil.
    Un profil est quoiqu'i larrive utilisateur, mais il peut être admin.
    Un profil a plusieurs propriétés (A,B) communes à un utilisateur et un admin
    Un utilisateur est défini par plusieurs propriétés (C,D) et a plusieurs méthodes
    Un admin est défini par plusieurs proprités (E,F) et a plusierus méthodes.


    Comment dois-je structurer ma classe pour pouvoir définir dans mon application un object profil P qui implémentera quoiqu'il arrive un objet User U et dans certains cas, un objet Admin A.


    Merci grandement pour vos réponses !!!!

  2. #2
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    euh

    une interface IProfil et ensuite :

    classe Utilisateur : public IProfil

    etc...

    The Monz, Toulouse

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Par défaut
    Une classe "Personnes" (ou "Profil", comme tu dis), éventuellement abstraite. Les propriétés et méthodes communes aux différents types d'utilisateurs sont codées dans cette classe.
    Deux classes "Admin" et "User" qui héritent de cette classe et qui implémentent leur propres méthodes et propriétés.
    Possiblité de rajouter toutes sortes d'utilisateurs en implémentant de nouvelles classes de "Personnes".

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    801
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 801
    Par défaut
    Merci pour ta réponse theMonz31,
    Cependant, je n'arrive pas bien à comprendre le concept d'interface.
    C'est une partie de la classe qu'il faut implémentée quand on en instancie un objet ?

    une interface peut-elle contenir des méthodes ?

  5. #5
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    l'interface te permet de décrire un comportement "obligatoire" pour les classes
    qui implémenteront cette interface

    On compare souvent les interfaces aux classes abstraites... ca peut te donner
    une idée...

    Sauf qu'implémenter une interface t'oblige à implémenter (quit à ce que les méthodes ne fassent rien) les méthodes, accesseur , event declaré dans l'interface

    LA seule chose qu'on ne peut faire dans une interface, c'est du code...

    Donc, des accesseurs, event, méthode, etc.. mais pas de code, ni de déclaration de variables.

    The Monz, Toulouse

  6. #6
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    j'oubliais

    Avantage des interfaces (peut-etre pas dans ton cas) , une classe peut
    implémenter plusieurs interfaces.. alors que l'héritage multiple n'est pas
    supporté par .Net (que ca soit C++.Net ou C#, ou VB.Net)

    The Monz, Toulouse

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Par défaut
    Une interface contient uniquement des signatures de méthodes. C'est une sorte de "contrat" qui certifie que toutes les classes dérivant de cette interface implémenteront les méthodes en question, de manière publique.
    C'est parfois considéré comme plus "propre" qu'une classe abstraite, en particulier parce qu'une classe peut hériter de plusieurs interfaces mais d'une seule classe. Mais on ne peut pas y mettre de propriétés ou de code... Juste les signatures des méthodes, aucune implémentation.

    Pour choisir entre une interface et une classe abstraite... et bien ça dépend du programme. D'après la façon dont tu as défini ton problème, une classe abstraite me semblait plus appropriée, mais ça reste à voir.

    Essaie de trouver quelques cours ou tutos sur le sujet pour y voir plus clair, c'est tout de même une des bases de la programmation objet :p



    EDIT : bon j'en ai marre que theMonz31 réponde à chaque fois pendant que je rédige MA réponse Nan je ne t'en veux pas, c'est juste un peu vexant d'avoir l'impression de répéter ce qu'a dit le précédent

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    801
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 801
    Par défaut
    En fait, on pourrait dire, qu'une interface est une classe abstraite qui n'a que des méthodes abstraites.

  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Par défaut
    oui c'est ça

  10. #10
    Rédacteur
    Avatar de Thomas Lebrun
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    9 161
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 9 161
    Par défaut
    Une interface est un contrat qui ne contient que des signatures de méthodes/propriétés: toutes les classes qui implémentent l'interface devront implémenter ces méthodes/propriétés


    Edit: Oops, pas vu que Astartee avait déjà fait la laïus sur les interfaces

  11. #11
    Rédacteur
    Avatar de SaumonAgile
    Homme Profil pro
    Team leader
    Inscrit en
    Avril 2007
    Messages
    4 028
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Team leader
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2007
    Messages : 4 028
    Par défaut
    Je suis d'accord avec la solution de Astartee.
    De mon point de vue, les profils ont des propriétés et des comportements communs qu'ils peuvent hériter d'une classe de base.
    A contrario l'utilisation d'une interface obligerait à dupliquer le code correspondant aux comportements communs.

    MTC.

    EDIT : Clarification : MTC ne signifie pas 'mange ton choux', mais simplement 'My Two Cents'
    Besoin d'un MessageBox amélioré ? InformationBox pour .NET 1.1, 2.0, 3.0, 3.5, 4.0 sous license Apache 2.0.

    Bonnes pratiques pour les accès aux données
    Débogage efficace en .NET
    LINQ to Objects : l'envers du décor

    Mon profil LinkedIn - MCT - MCPD WinForms - MCTS Applications Distribuées - MCTS WCF - MCTS WCF 4.0 - MCTS SQL Server 2008, Database Development - Mon blog - Twitter

  12. #12
    Membre émérite
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    652
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 652
    Par défaut
    Je vote aussi pour la version d'Astartee. Pas vraiment d'intérêt à l'interface dans ce cas-là, surtout vu que ça empêche de mettre les méthodes communes... en commun :)

    Bon après, rien n'empêche d'avoir une interface en plus de la classe abstraite. Si jamais le code de la classe a une dépendance avec une librairie/ressource particulière, l'interface peut découpler tout ça et (notamment) faciliter les tests.

  13. #13
    Membre éprouvé

    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Par défaut
    Finalement, un profil est toujours un utilisateur, donc tu as le meme concept, donc tu peux regrouper ca dans un seul objet.

    Sinon, tu fais une classe abstraite Profil, puis une classe Utilisateur (pas abstraite) qui derive de Profil, puis une classe Admin (pas abstraite) qui derive de Utilisateur.

  14. #14
    Membre éprouvé

    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Par défaut
    De cette maniere quand tu veux un utilisateur, tu fais
    et si tu veux un admin

  15. #15
    Membre émérite
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    652
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 652
    Par défaut
    (ce qui est donc la version d'Astartee :)
    (c'est bien quand tout le monde est d'accord :)

  16. #16
    Membre éprouvé

    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Par défaut
    Pas tout a fait puisque je fais deriver Admin de User, puisque un admin reste un user

  17. #17
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    801
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 801
    Par défaut
    Je suis parti la dessus.

    J'ai:

    - une classe profil abstraite.
    - une classe employee qui dérive de profil
    - une classe signatory (plus admin) qui dérive d'employee

    Je voudrais vous montrer le début des 3 classes pour que vous me disiez si ça convient.

    <u>classe profil</u>
    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
     
    public abstract class Profil
    {
        private string _sgi;
     
        private bool _isEmployee;
        private bool _isSignatory;
     
        private int _employeeID;
        private int _signatoryID;
     
        public abstract void loadTreeView(TreeView t);    
     
        public Profil(string sgi)
    	{
            this._sgi = sgi;
            this.getProfile();
    	}
     
     
     
        /// <summary>
        /// Défini si le profil employee, signataire du user. Retourne true si l'employee est signataire, false sinon.
        /// </summary>
        /// <returns>true,false</returns>
        protected void getProfile()
        {
     
            SqlConnection con = new SqlConnection(variables.ConnectionString);
            SqlCommand cmd = new SqlCommand(sqlProc.RA_getProfile, con);
            cmd.CommandType = CommandType.StoredProcedure;
            SqlParameter paramSGI;
            SqlParameter paramIdEmployee;
            SqlParameter paramIdSignatory;
     
            paramSGI = cmd.Parameters.Add(sqlProc.RA_getProfile_in_sgi, SqlDbType.VarChar, 8);
            paramSGI.Direction = ParameterDirection.Input;
            cmd.Parameters[sqlProc.RA_getProfile_in_sgi].Value = this.SGI;
     
            paramIdEmployee = cmd.Parameters.Add(sqlProc.RA_getProfile_out_idemployee, SqlDbType.Int,6);
            paramIdEmployee.Direction = ParameterDirection.Output;
     
            paramIdSignatory = cmd.Parameters.Add(sqlProc.RA_getProfile_out_idsignatory, SqlDbType.Int, 4);
            paramIdSignatory.Direction = ParameterDirection.Output;
     
            con.Open();
            cmd.ExecuteNonQuery();
            con.Close();
     
     
            IsEmployee = (Convert.IsDBNull(cmd.Parameters[sqlProc.RA_getProfile_out_idemployee].Value)) ? false : true;
            IsSignatory = (Convert.IsDBNull(cmd.Parameters[sqlProc.RA_getProfile_out_idsignatory].Value)) ? false : true;
     
            EmployeeId = (Convert.IsDBNull(cmd.Parameters[sqlProc.RA_getProfile_out_idemployee].Value))?0:(int)cmd.Parameters[sqlProc.RA_getProfile_out_idemployee].Value;
            SignatoryId = (Convert.IsDBNull(cmd.Parameters[sqlProc.RA_getProfile_out_idsignatory].Value)) ? 0 : (int)cmd.Parameters[sqlProc.RA_getProfile_out_idsignatory].Value;
     
     
        }
     
        #region acesseurs
        /// <summary>
        /// SGI de l'employee loggé
        /// </summary>
        public string SGI
        {
            get { return _sgi; }
            private set { _sgi = value; }
        }
        /// <summary>
        /// bool qui indique si le profil est employée
        /// </summary>
        public bool IsEmployee
        {
            get { return _isEmployee; }
            private set { _isEmployee = value;}
        }
        /// <summary>
        /// bool qui indique si le profil est signataire
        /// </summary>
        public bool IsSignatory
        {
            get { return _isSignatory; }
            private set { _isSignatory = value; }
        }
        /// <summary>
        /// identifiant ID_EMPLOYEE de la BD. 0 si non employee
        /// </summary>
        public int EmployeeId
        {
            get { return _employeeID; }
            private set { _employeeID = value; }
        }
        /// <summary>
        /// identifiant ID_SIGNATORY de la BD. 0 si non signataie
        /// </summary>
        public int SignatoryId
        {
            get { return _signatoryID; }
            private set { _signatoryID = value; }
        }
     
        #endregion
    <u>classe employee</u>
    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
     
    public class Employee:Profil
    {
     
        public Employee(string sgi):base(sgi)
    	{
     
        }
        public override void loadTreeView(TreeView t)
        {
            TreeNode tn = new TreeNode(base.SGI);
            tn.ChildNodes.Add(new TreeNode("Raise an RA"));
            tn.ChildNodes.Add(new TreeNode("RA being processed"));
            tn.ChildNodes.Add(new TreeNode("RA historic"));
            t.Nodes.Add(tn);
        }
    <u>classe signatory</u>
    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
     
    public class Signatory:Employee
    {
    	public Signatory(string sgi):base(sgi)
    	{
     
        }
        public override void loadTreeView(TreeView t)
        {
            base.loadTreeView(t);
            TreeNode tn = new TreeNode("Signatory");
            tn.ChildNodes.Add(new TreeNode("RA to sign"));
            tn.ChildNodes.Add(new TreeNode("RA I signed"));
            t.Nodes.Add(tn);
        }
     
    }

    J'ai encore deux petites questions ....:

    Si je déclare d'autres méthodes abstraites dans ma classe profil qui ne servira que dans la classe employee, dois-je aussi obligatoirement la définir dans la classe signatory ?

    Si je déclare une méthode non abstraite dans ma classe employee, comment pourrais y accéder depuis la classe profil ?



    Merci, en tout cas, pour la participation qui me fait beaucoup avancer !!!

  18. #18
    Membre émérite
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Par défaut
    Une classe non abstraite ne peut pas contenir de membre abstrait. Donc si elle dérive d'une classe qui définit une méthode abstraite, elle doit l'implémenter.

    Si la fonction est destinée à être utilisée uniquement par la classe Employee, il ne faut donc la définir que pour cette classe.
    Pour l'utiliser, il faudra alors "caster" l'objet pour indiquer qu'il est de type Employee :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Profil unProfil = ...;
    // je sais que unProfil est bien un Employee
    ((Employee)unProfil).maFonctionSpecialeEmployee();
    Comme la fonction n'est pas destinée à être utilisée pour les Signatory, cela signifie que dans ton code, au moment où tu veux l'appeler, tu sais que le Profil considéré est un Employee. Donc le cast ne devrait pas poser de problème.

  19. #19
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    801
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 801
    Par défaut
    Et oui tout à fait !!!

    Merci bien pour cette réponse ! C'était un peu confus mais maintenant c'est clair :
    Comme la fonction n'est pas destinée à être utilisée pour les Signatory, cela signifie que dans ton code, au moment où tu veux l'appeler, tu sais que le Profil considéré est un Employee. Donc le cast ne devrait pas poser de problème.
    C'est ça qui me manquait pour bien comprendre !!
    Donc pas d'erreur possible, c'est tout bon !
    Merci encore !

  20. #20
    Membre émérite
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    652
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 652
    Par défaut
    Citation Envoyé par davidou2001
    Pas tout a fait puisque je fais deriver Admin de User, puisque un admin reste un user
    Certes. Ça m'apprendra à poster endormi. Cela dit, du coup une classe concrète dérive d'une autre, et vu que plus ça va, plus j'ai tendance à éviter ça...

    Cela dit (bis), si admin dérive de user et que user est le seul dérivé de profil, user et profil peuvent être combinés (sinon comment déterminer ce qui dépend de profil et ce qui dépend de user ? la limite est très floue). Donc zou, regroupement en une classe profil. Et ensuite de la classe profil, on pourrait dériver une classe user sans grand chose de spécifique, dans le seul but de séparer clairement les admins des utilisateurs.

    La grande question est au niveau du design/domaine. Quelles sont exactement les relations entre profils, utilisateurs et admins ?

    Un utilisateur est un profil, un administrateur aussi, mais est-ce qu'un administrateur est un utilisateur 'normal' ? Ça dépend de ce qu'on implique par 'utilisateur'. Si c'est dans le sens 'compte', oui. Mais c'est synonyme de profil, justement. Si 'utilisateur' veut dire 'utilisateur standard', alors un administrateur n'en est pas un. Donc pas de dérivation entre les deux.

    (d'où l'importance d'éclaircir les concepts du domaine avant de se préoccuper du code :)

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

Discussions similaires

  1. Réponses: 19
    Dernier message: 05/06/2007, 08h13
  2. Réponses: 12
    Dernier message: 12/12/2004, 14h25
  3. Réponses: 3
    Dernier message: 01/02/2004, 21h24
  4. Informations sur les procédures stockées
    Par jfphan dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 13/01/2004, 14h30
  5. Réponses: 6
    Dernier message: 28/09/2003, 17h49

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