Partage
  • Partager sur Facebook
  • Partager sur Twitter

Refuser/autoriser l'instantiation d'un objet

constructeurs

Sujet résolu
    16 mars 2011 à 15:59:40

    Bonjours à tous.

    Je suis actuellement sur du C#, et j'aimerais savoir si il est possible de créer une restriction lol de la création d'un objet au niveau de son constructeur.

    Par exemple :

    J'ai 2 objets Personnes, qui peuvent se marier avec une methode prévus pour (celle ci créer un nouvel objet Personne)
    J'aimerais savoir si il est possible dans le constructeur de 'Personne' d'ajouter une vérification pour 'annuler' la construction de l'objet.

    Ceci par exemple pour empecher un pére de se marier avec sa fille :euh:

    J'espére que vous avez saisie ce que je veux dire =) si ce n'est pas le cas j'essayerais de vous réxpliquer ^^

    Je vous remercie d'avance pour vos éventuelles réponses
    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      16 mars 2011 à 16:45:02

      Rend ton constructeur private, et crée une méthode statique Personne.CréerPersonne() prenant ce que tu veux en paramètres (la mère, le père...) qui renvoie une Personne si c'est possible et null (ou une variable de type Personne constante, genre Personne.Erreur, si tu veux que ça soit plus compréhensible) sinon.
      Ou alors lance une exception dans le constructeur (mais c'est pas très beau).
      • Partager sur Facebook
      • Partager sur Twitter
        16 mars 2011 à 17:38:23

        Le mieux est effectivement de rendre le constructeur private et de passer par une méthode statique qui se chargera d'instancier un nouvel objet après avoir fait la/les validation/s nécessaire/s.

        Tu peux éventuellement prévoir un paramètre booléen à cette méthode qui permettra d'indiquer ce qu'on veut qu'elle fasse si la validation échoue : renvoyer null ou lancer une exception ;)
        • Partager sur Facebook
        • Partager sur Twitter
          16 mars 2011 à 18:34:16

          je l'imaginerais comme ça :
          class Personne
              {
                  private string _nom;
                  private string _prenom;
                  private Personne _mere = null;
                  private Personne _pere = null;
                  private List<Personne> _enfants = new List<Personne>();
          
                  //Getters & Setters
                  public string Nom
                  {
                      get { return _nom; }
                      set { _nom = value; }
                  }
                  
                  //etc pour chaque champs ...
                  
                  //Constructeurs
                  public Personne(string nom, string prenom)
                  {
                      this._nom = nom;
                      this._prenom = prenom;
                  }
          
                  public Personne(string nom, string prenom, Personne pere, Personne mere)
                  {
                      this._nom = nom;
                      this._prenom = prenom;
                      this._pere = pere;
                      this._mere = mere;
                  }
          
                   //Ajoute un enfant, retourne faux s'il n'y a pas d'insceste et ajoute un objet personne aux enfants des parents
                  public static bool ajouterEnfant(string prenom, Personne parent1, Personne parent2)
                  {
                      bool insceste = false;
          
                      //On vérifie que le parent1 n'appartient pas à la collection d'enfants du parent2 et vice versa
                      foreach (Personne enfant in parent1.Enfants)
                      {
                          if (enfant == parent2)
                              insceste = true;
                      }
          
                      foreach (Personne enfant in parent2.Enfants)
                      {
                          if (enfant == parent1)
                              insceste = true;
                      }
          
                      if (!insceste)
                      {
                          //On crée un enfant qui porte le nom des parents
                          Personne enfant = new Personne(parent1.Nom, prenom, parent1, parent2);
          
                          //On ajoute l'enfant au pere et a la mere
                          parent1.Enfants.Add(enfant);
                          parent2.Enfants.Add(enfant);
                      }
          
                      return insceste;
                  }
          


          et dans le main tu aurais:
          Personne adam = new Personne("adamNom", "adam");
          Personne eve = new Personne("eveNom", "eve");
          
          bool insceste = Personne.ajouterEnfant("toto", adam, eve);
          
          if (insceste)
              Console.WriteLine("Aucun enfant n'a ete ajoute");
          else
              Console.WriteLine(adam.Prenom + " et " + eve.Prenom + " ont eu un enfant");
          
          • Partager sur Facebook
          • Partager sur Twitter
            16 mars 2011 à 20:12:12

            Quelques remarques:
            - il faudrait rendre les constructeurs private;
            - quitte à renvoyer un booléen, autant renvoyer false si l'opération a échoué;
            - tu peux utiliser la méthode Contains pour tester si une liste contient un élément
            :)
            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              16 mars 2011 à 20:27:56

              J'me permets d'autres remarques :
              -Si les getters et setters ne font qu'obtenir et modifier la valeur de la variable, autant utiliser la syntaxe
              public string MaVariable {get; set;}
              

              -Les méthodes sont censées être en PascalCasing (oui, je cherche la petite bête)
              -Ne pas mettre d'accolades dans les if/else c'est moche
              • Partager sur Facebook
              • Partager sur Twitter
                16 mars 2011 à 20:44:36

                Si je met le constructeur en private, je ne pourrais pas créer d'instances de ma classe en dehors d'elle même.
                • Partager sur Facebook
                • Partager sur Twitter
                  16 mars 2011 à 21:37:32

                  Aethec: effectivement, il aurait fallu préciser ça aussi :)

                  Citation : Mr 73r0

                  Si je met le constructeur en private, je ne pourrais pas créer d'instances de ma classe en dehors d'elle même.


                  Et c'est précisément le but recherché ;)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    16 mars 2011 à 22:05:36

                    Merci les gars c'est juste ce qu'il me faut ^^
                    Encore merci a tous ;)
                    • Partager sur Facebook
                    • Partager sur Twitter
                      16 mars 2011 à 22:17:15

                      Citation : Orwell

                      Aethec: effectivement, il aurait fallu préciser ça aussi :)

                      Citation : Mr 73r0

                      Si je met le constructeur en private, je ne pourrais pas créer d'instances de ma classe en dehors d'elle même.


                      Et c'est précisément le but recherché ;)



                      Comment ça c'est le but ?
                      Cette ligne ne compilera pas.

                      Personne adam = new Personne("adamNom", "adam");
                      


                      • Partager sur Facebook
                      • Partager sur Twitter
                        16 mars 2011 à 22:34:47

                        D'où l'intérêt d'avoir une méthode statique publique qui elle pourra appeler le constructeur privé, et donc créer une nouvelle instance.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          16 mars 2011 à 22:38:24

                          Simple application du pattern Factory :)
                          • Partager sur Facebook
                          • Partager sur Twitter
                            16 mars 2011 à 22:48:29

                            Citation : Strimy

                            D'où l'intérêt d'avoir une méthode statique publique qui elle pourra appeler le constructeur privé, et donc créer une nouvelle instance.



                            Il y a un truc que je ne dois pas comprendre. Quelle intérêt de faire une fonction public qui appelle un constructeur privé, quand on peut directement mettre ce constructeur en public ?
                            • Partager sur Facebook
                            • Partager sur Twitter
                              16 mars 2011 à 23:02:48

                              L'intérêt est de permettre une validation autorisant ou non l'instanciation d'un objet sans placer celle-ci (la validation) au niveau du constructeur. Le "problème" est que l'appel à un constructeur ne peut pas être neutralisé, car il n'est pas possible d'obtenir une valeur nulle comme résultat. Une solution est de lancer une exception si nécessaire, mais c'est à éviter. En forçant l'utilisateur de la classe à passer par une méthode statique plutôt que par son constructeur, on gagne en flexibilité :)
                              • Partager sur Facebook
                              • Partager sur Twitter
                                16 mars 2011 à 23:14:43

                                Je veux bien voir un exemple, je ne sais même pas comment appeler le constructeur sans créer d'instance.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  16 mars 2011 à 23:54:43

                                  Voici un exemple inspiré de ton code :

                                  public class Personne
                                  {
                                      private List<Personne> _enfants = new List<Personne>();
                                  
                                      public string Prenom { get; private set; }
                                      public string Nom { get; private set; }
                                      public Personne Pere { get; private set; }
                                      public Personne Mere { get; private set; }
                                      public ReadOnlyCollection<Personne> Enfants { get { return new ReadOnlyCollection<Personne>(_enfants); } }
                                  
                                      private Personne(string prenom, string nom, Personne pere = null, Personne mere = null)
                                      {
                                          this.Prenom = prenom;
                                          this.Nom = nom;
                                          this.Pere = pere;
                                          this.Mere = mere;
                                      }
                                  
                                      public static Personne CreerEnfant(string prenom, Personne pere, Personne mere, bool exceptionSiInceste = true)
                                      {
                                          if(pere._enfants.Contains(mere) || mere._enfants.Contains(pere))
                                          {
                                              if(exceptionSiInceste)
                                                  throw new ExceptionDivine("Avec ta famille tu ne copuleras point !");
                                              return null;
                                          }
                                  
                                          //On crée un enfant qui porte le nom des parents
                                          Personne enfant = new Personne(prenom, pere.Nom, pere, mere);
                                  
                                          //On ajoute l'enfant au pere et a la mere
                                          pere._enfants.Add(enfant);
                                          mere._enfants.Add(enfant);
                                  
                                          return enfant;
                                      }
                                  
                                      public static Personne CreerOrphelin(string prenom, string nom)
                                      {
                                          return new Personne(prenom, nom);
                                      }
                                  
                                      private static Personne _adam;
                                      public static Personne Adam { get { return _adam ?? (_adam = CreerOrphelin("Adam", "Dujardin d'Eden")); } }
                                  
                                      private static Personne _eve;
                                      public static Personne Eve { get { return _eve ?? (_eve = CreerOrphelin("Eve", "Dujardin d'Eden")); } }
                                  }
                                  


                                  Avec ça tu peux créer tous les enfants que tu veux, qu'ils soient orphelins ou non:
                                  Personne cain = Personne.CreerEnfant("Cain", Personne.Adam, Personne.Eve);
                                  Personne nobody = Personne.CreerEnfant("Oups", cain, Personne.Eve); // pas bien !
                                  Personne oliver = Personne.CreerOrphelin("Oliver", "Twist");
                                  

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    17 mars 2011 à 0:12:36

                                    D'accord, au lieu d'avoir 2 constructeurs, tu as 2 méthodes. C'est la première fois que je rencontre ce pattern et je t'avouerais que j'en vois pas l'intérêt ici, mais c'est peut-être pas un cas de figure où il est le plus adapté.
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      17 mars 2011 à 0:16:21

                                      L'intérêt de la méthode CreerOrphelin est assez discutable, on pourrait très bien créer une surcharge publique du constructeur avec ces deux paramètres. Mais puisqu'on passe par une méthode pour instancier des objets dans au moins un cas, autant passer par des méthodes pour tous les cas; ça me paraît plus cohérent. :)
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        17 mars 2011 à 9:03:48

                                        Citation

                                        private List<Personne> _enfants = new List<Personne>();



                                        Petite question, comment je puis faire pour afficher le contenue de la clooection ?

                                        [EDIT] Non c'est bon j'ai trouvé, encore merci a tous ^^
                                        • Partager sur Facebook
                                        • Partager sur Twitter

                                        Refuser/autoriser l'instantiation d'un objet

                                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                        • Editeur
                                        • Markdown