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#] Surcharge de constructeur


Sujet :

C#

  1. #1
    Membre régulier
    Inscrit en
    février 2004
    Messages
    206
    Détails du profil
    Informations forums :
    Inscription : février 2004
    Messages : 206
    Points : 74
    Points
    74
    Par défaut [C#] Surcharge de constructeur
    Bonjour,

    je viens ici pour demander de l'aide à propos de la surcharge de constructeur.
    Je suis sur un site qui me semble un bon cours pour ma compréhension du C# POO. Je me suis donc inspiré d'un exemple existant pour illustrer quelque chose que je n'arrive pas à comprendre. Dans l'exemple ci-dessous j'instancie l'objet Chien de 2 façons Chien chien1 = new Chien() et Chien chien2 = new Chien("chien1"). Dans le premier j'obtiens les résultats que je souhaite donc car pour moi un chien1 est construit d'abord en tant qu'Animal sans argument puis en tant que Chien sans argument. PAr contre je ne comprends pas pourquoi pour l'objet chien2 j'ai le résultat un animal vient d'être créé sans argument et un nouveau chien vient d'être créé avec la variable chien2. Je m'attendais à voir d'abord : Un animal chien2 vient d'être créé !!! puis un nouveau chien vient d'être créé avec la variable chien2.
    J'espère avoir été clair dans la façon d'expliquer mon problème. Merci.
    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
     
    using System;
     
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Chien chien1 = new Chien();
                Chien chien2 = new Chien("chien2");
            }
        }
     
        class Animal
        {
            public string v1;
     
            /**
             * constructeur de notre classe animal
             */
            public Animal()
            {
                Console.Out.WriteLine("Un animal vient d'être créé sans argument");
            }
     
            public Animal(string nomVariable)
            {
                Console.Out.WriteLine("Un animal" + nomVariable + " vient d'être créé !!!");
                this.v1 = nomVariable;
            }
          }
     
     
        class Chien : Animal
        {        
            public Chien()
            {
                Console.Out.WriteLine("un nouveau chien sans argument vient d'être créé");
            }
     
            public Chien(string nomVariable)
            {
                Console.Out.WriteLine("un nouveau chien vient d'être créé avec la variable " + nomVariable);
            }
     
        }
    }

  2. #2
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Lorsque tu instancies un objet dérivé il y a toujours un appel à un des constructeurs de la classe parent.

    Cet appel est soit implicite, le constructeur par défaut de la classe parent est alors utilisé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public Chien()
    {
        ...
    }
    Revient à écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public Chien() : base()
    {
        ...
    }
    Le mot clé base permettant d'indiquer le constructeur de la classe parent à utiliser pour l'instanciation.

    Soit explicite, dans ce cas on indique le constructeur de la classe parent à utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public Chien(string nomVariable) : base(nomVariable)
    {
        ...
    }
    Pas de questions techniques par MP

  3. #3
    Membre régulier
    Inscrit en
    février 2004
    Messages
    206
    Détails du profil
    Informations forums :
    Inscription : février 2004
    Messages : 206
    Points : 74
    Points
    74
    Par défaut
    merci Je ne connaissais pas ce mot clé et son utilisation. Miantenant mon programme exemple fonctionne correctement.

    Merci pour tes explications.

  4. #4
    Membre éclairé
    Inscrit en
    octobre 2006
    Messages
    587
    Détails du profil
    Informations personnelles :
    Âge : 35

    Informations forums :
    Inscription : octobre 2006
    Messages : 587
    Points : 706
    Points
    706
    Par défaut
    Tu peux appeler le constructeur de la classe mère mais tu peux aussi appeler les constructeurs surchargés ou non de ta classe avec le mot clé this

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    //Ce constructeur appellera explicitement  le constructeur Chien() de la même classe avec d'exécuter ses instructions.
    public Chien(string chaine) : this()
    {
     
    }

  5. #5
    Membre régulier
    Inscrit en
    février 2004
    Messages
    206
    Détails du profil
    Informations forums :
    Inscription : février 2004
    Messages : 206
    Points : 74
    Points
    74
    Par défaut
    Merci Harz,

    c'est un aspect que je n'ai pas trouvé dans le cours que j'utilise.
    A+

  6. #6
    Membre à l'essai
    Inscrit en
    mars 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 29
    Points : 15
    Points
    15
    Par défaut
    Je relance le sujet par une nouvelle question : peux t on avoir les deux en même temps (this & base) dans la surcharge d'un constructeur ?

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class A
    {
       A()
       A(int i):this()
       A(int i, int j):this(i)
    }
     
    public class B : A
    {
       B()
       B(int k):this() & base()
       B(int k, int l):this(k) & base(k)
    }

  7. #7
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    octobre 2007
    Messages
    4 412
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : octobre 2007
    Messages : 4 412
    Points : 2 494
    Points
    2 494
    Par défaut
    Essayer soi meme peut aussi aider et est parfois plus rapide que de poser la question et attendre la reponse
    « Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain)

  8. #8
    Membre à l'essai
    Inscrit en
    mars 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 29
    Points : 15
    Points
    15
    Par défaut
    Tout à fait et je ne suis pas arrivé à trouver la syntaxe. C'est bien pour cela que je pose la question.

    Du coup, afin d'avoir une confirmation dans un sens ou dans l'autre et de ne pas rester sur un doute, je souhaitais demander à la communauté si ce moyen existe ou pas.

  9. #9
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    octobre 2007
    Messages
    4 412
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : octobre 2007
    Messages : 4 412
    Points : 2 494
    Points
    2 494
    Par défaut
    Qu'est ce que tu veux faire exactement ?
    « Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain)

  10. #10
    Membre à l'essai
    Inscrit en
    mars 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 29
    Points : 15
    Points
    15
    Par défaut
    La question est : Depuis un constructeur surchargé d'une classe dérivée, peut on appeler un autre constructeur de la classe dérivée ET également un constructeur de la classe de base.

    Exemple parlant :
    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
    // Classe de base A
    public classe A
    {
        // Ayant deux attributs
        public readonly int a1;
        public int a2;
    
        // Le 1er initialisé dans le constructeur par défaut
        public A()
        {
          this.a1= 10;
        }
    
        // Le 2eme initialisé dans le constructeur avec argument
        // et qui fait appel au constructeur par défaut
        public A(int a2):this()
        {
          this.a2= a2;
        }
    }
    
    // Classe B dérivée de la classe A
    public classe B : A
    {
        // Un seul argument
        public readonly int b1;
    
        // Initialisé dans le constructeur par défaut
        public B()
        {
          this.b1= 11;
        }
        // Un consctructeur avec argument qui appelle le constructeur par défaut
        // et le constructeur de base avec un argument
        // Attention cette syntaxe ne fonctionne pas
        public B(int b2):this(), base(b1)
        {      
        }
    }
    Le but est de savoir si on peut faire ce double appel afin d'éviter de dupliquer du code dans un constructeur donné. C'est juste une question de culture.

  11. #11
    Membre éprouvé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    juin 2011
    Messages
    487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : juin 2011
    Messages : 487
    Points : 945
    Points
    945
    Par défaut
    J'ai déjà cherché, et voyant que ce n'était pas apparemment possible, suis mis à me poser des questions. Au final, cela relève un peu d'un problème de conception. Il suffit de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public A() : base()
    {
    }
     
    public A(string s) : this()
    {
    }
    Du coup, A(string s) appelle indirectement base().
    Mon blog sur les technos .NET et Agile -> http://blog.developpez.com/maximepalmisano/

  12. #12
    Candidat au Club
    Homme Profil pro
    Inscrit en
    juillet 2011
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : juillet 2011
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    Bon, j'ai buté sur ce problème, car la solution proposé ne permet pas de résoudre certains cas, où il est nécessaire d'appeler le constructeur au milieu ou à la fin et non pas au début.

    La solution que j'ai trouvé, c'est poser le contenu des constructeurs dans des méthodes protected du style :

    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
     
     
    public class ClassA
    {
        public ClasseA() { construct(); }
        public ClasseA(typeA a, typeB b,typeC c) : this() { construct(a,b,c); }
     
        protected void construct()
        {
        // Mon code de constructeur vide
        }
     
        protected void construct(typeA a, typeB b,typeC c)
        {
        // Mon code de constructeur avec arguments
        }
     
    }
    Ce qui permet dans une classe B de l'appeler au sein même du constructeur.
    Ou d'appeler éventuellement plusieurs constructeurs différents.
    Ou, pour le cas qui m'embétait, appeler le constructeur avec des données travaillées.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public class ClasseB : ClasseA
    {
        public ClasseB : base() // Appel du constructeur vide de A initial
        {
        // Début de constructeur classe B (ex : fabrication des arguments)    
     
        base.construct(a,b,c);
     
        // Fin de constructeur classe B
        }
     
    }
    C'est pas extraordinairement élégant, puisqu'on pourrait potentiellement appeller un constructeurs au sein même d'autres méthodes...
    (alors que je préfèrerai parfois laisser le code des constructeurs uniquement au sein d'un constructeurs)

    Mais ça permet de faire à peu près ce qu'on veux, en se payant même le luxe de laisser private les propriétés private de A qu'on souhaitait modifier lors de la construction.

    Note :
    Il est nécessaire de redéfinir chaque méthode construct avec un new à chaque échelon.

    Et il est conseillé de bloquer l'héritage des constructeurs de A dans B.
    Pour éviter qu'une ClasseC héritant de ClasseB utilise malencontreusement un constructeur de A en pensant utiliser un de B...

    C'est ces contraintes qui font que c'est moyennement propre comme technique. ça peut entrainerdes bug si on fait pas gaffe.

    L'aventage de la méthode, c'est que tous les constructeurs de A peuvent être posé l'un en dessous de l'autre chacun sur une ligne.
    Ce qui (je trouve) rend beaucoup plus clair la comparaison entre les différents constructeurs accessible au sein de la classe. (surtout si on en a 5 ou 6)

    Un autre aventage, c'est qu'on peut aussi du coup poser au sein des interfaces les indications sur les constructeurs à construire pour chacun des éléments.

  13. #13
    Membre éprouvé
    Avatar de landry161
    Homme Profil pro
    C#,PHP,MySQL,Android...
    Inscrit en
    juillet 2010
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : C#,PHP,MySQL,Android...

    Informations forums :
    Inscription : juillet 2010
    Messages : 423
    Points : 1 060
    Points
    1 060
    Billets dans le blog
    1
    Par défaut
    public A() : base()
    {
    }

    c est de l héritage

  14. #14
    Membre éprouvé
    Avatar de landry161
    Homme Profil pro
    C#,PHP,MySQL,Android...
    Inscrit en
    juillet 2010
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : C#,PHP,MySQL,Android...

    Informations forums :
    Inscription : juillet 2010
    Messages : 423
    Points : 1 060
    Points
    1 060
    Billets dans le blog
    1
    Par défaut
    public A() : base()
    {
    }

    Notion d' héritage dans le concept de la POO

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

Discussions similaires

  1. Surcharger un constructeur de classe
    Par pdgnr dans le forum C++Builder
    Réponses: 5
    Dernier message: 09/11/2006, 10h17
  2. [POO] Surcharge de constructeur
    Par loganblack dans le forum Langage
    Réponses: 4
    Dernier message: 17/05/2006, 12h26
  3. Réponses: 19
    Dernier message: 19/04/2006, 10h16
  4. [POO] surcharger le constructeur
    Par wdionysos dans le forum Langage
    Réponses: 9
    Dernier message: 22/03/2006, 15h42
  5. Surcharge de constructeur???
    Par Sunsawe dans le forum Général Python
    Réponses: 3
    Dernier message: 14/03/2006, 17h26

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