Partage
  • Partager sur Facebook
  • Partager sur Twitter

foreach( B in list<A>) avec B héritant de A

    6 octobre 2019 à 21:15:50

    Bonjour,

    Je voudrais savoir s'il est possible dans une liste de type A de faire un foreach qui ressort seulement les objets de type B, sachant que B hérite de A.

    J'ai fait ça pour le moment mais ça me dit que ça peut pas caster la liste de type A en B.

    foreach (B b in mesA)
    {
       //do something
    }



    Merci,

    Bonne soirée.

    -
    Edité par yoyo22 6 octobre 2019 à 21:19:10

    • Partager sur Facebook
    • Partager sur Twitter
      7 octobre 2019 à 11:12:21

      > faire un foreach qui ressort seulement les objets de type B, sachant que B hérite de A.

      "ressortir" n'est pas un terme très clair pour expliquer ce que tu veux faire.

      * Si mesA est une liste de  Personnage, on ne peut pas la parcourir avec un foreach dont la variable de contrôle est du type dérivé Schtroumpf,

      C'est parfaitement logique, parce que la liste peut contenir des personnage qui ne sont pas des Schtroumpf, et ne savent pas schtroumpfer.

      foreach (Schtroumpf s in mesPersonnages)   // incorrect
      {
          s.schtroumpfer();     
      }

      Et le compilateur a raison de refuser.

      * Si on veut faire schtroumpfer les personnages qui sont des Schtroumpfs, il faut tester le type (*), et "transtyper"

      foreach (Personnage p in mesPersonnages)
      {
          Schtroumpf s = p as Schtroumpf;   // marche, mais révélateur
          if ( s!= null ) {                 // d'une mauvaise conception
               s.schtroumpfer();
          }
      }
      
      

      (*) ce qui, dans 99% des cas présentés par des débutants (dont celui-ci), est révélateur d'une très mauvaise conception au départ.

      Si on a besoin de faire quelque chose avec les schtroumps et à eux seulement, on fait une liste de schtroumpfs. Y a pas de "je suis malin et je vais pas m'emmerder à avoir deux listes" qui tienne. Ca apporte des tas d'emmerdements, donc ce n'est pas malin du tout.

      Ou alors on fait remonter la méthode "schtroumpfer()" au niveau des Personnages, en disant que par défaut elle ne fait rien. Elle sera redéfinie pour les Schtroumpfs.



      -
      Edité par michelbillaud 7 octobre 2019 à 11:19:23

      • Partager sur Facebook
      • Partager sur Twitter
        7 octobre 2019 à 11:14:08

        • Partager sur Facebook
        • Partager sur Twitter
        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
          25 février 2020 à 14:02:44

          Quand t'as plein d'héritages différents possibles c'est quand même plus simple de tout gérer dans une seule liste plutôt que d'avoir un liste pour chaque sous catégorie. Dans mon exemple j'ai que A et B, mais dans mon projet j'ai une dixaine de classes mère avec chacune une dixaine de classes filles
          • Partager sur Facebook
          • Partager sur Twitter
            25 février 2020 à 14:22:39

            @yoyo22, tout ton argumentaire est encore plus une preuve d'erreurs de conceptions à la chaine.

            Tu as quelques problèmes que tes erreurs de conceptions initiales ont initiés et c'est la boule de neige.

            >Quand t'as plein d'héritages différents possibles

            Pourquoi ?

            Quand il y a beaucoup d'héritages différents c'est souvent que l'héritage n'est pas la solution.

            L'héritage est tellement contaminant que c'est généralement la dernière options après les autres (composition, Design Patern de structures, etc...).

            L'héritage n'a pas à être un choix par défaut mais uniquement quand il est le plus adapté (car le retour arrière ou les évolutions structurantes sont très compliqués avec l'héritage).

            >c'est quand même plus simple de tout gérer dans une seule liste plutôt que d'avoir un liste pour chaque sous catégorie

            Le plus simple, c'est le plus simple à l'utilisation, pas à l'implémentation. Là, on n'a largement la preuve du contraire.

            Et pour la simplification de l'implémentation, faudrait que tu me prouve qu'avoir tout mélangé est plus simple que d'avoir des choses bien rangées: t'es pas rendu.

            > j'ai une dixaine de classes mère avec chacune une dixaine de classes filles

            C'est clairement aussi un cas qui sent largement les erreurs de conceptions : quand il y a multiplication des classes, les Design Patern ou les paradigmes type ECS ont montrés leur efficience par rapport à ces châteaux de cartes.

            Le problème, c'est que plus tu maitrises les arcanes du langage plus tu as des solutions pour contourner/compenser ton erreur initial.

            Si tu travailles en équipe, écoutes les autres, même les moins expérimentés, dont les questions candides te montreront l'impasse de ta démarche.

            -
            Edité par bacelar 25 février 2020 à 14:23:45

            • Partager sur Facebook
            • Partager sur Twitter
            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
              26 février 2020 à 8:57:37

              Si tu as des dizaines de classes mères et filles, je ne vois pas comment déclarer une liste de chaque type d'objet peut devenir plus long qu'écrire une boucle à chaque utilisation.
              • Partager sur Facebook
              • Partager sur Twitter
                10 mars 2020 à 16:57:27

                Pour donner un exemple afin que ce soit plus clair, imaginons un jeu de farming. Je veux pouvoir stocker dans une liste toutes les ressources disponible dans la zone A, sachant que ce ne sont pas forcément des ressources de même type. Je peux avoir dans la zone A des ressources de type Bois, de type Pierre, de type animale, céréale... J'aimerais pouvoir avoir par zone la possibilité d'avoir une liste contenant toutes mes ressources, lesquelles héritent toutes de la classe mère principale, "Ressource". 

                Si on regarde ce que proposent les design patterns, le design pattern factory semble répondre à mon besoin. Que ma classe ressource soit une classe ou une interface, je me retrouve confronté au même problème qui est que je veux pouvoir extraire de ma liste de Type "Ressource" seulement les ressources d'un certain type, comme le "Bois" par exemple.

                Je ne vois pas comment avoir un code bien optimisé en objet sans avoir recours à l'héritage. Et je ne me vois pas avoir une liste de ressource de chaque type pour chaque zone, ce qui m'obligerait à initialiser une nouvelle liste si un nouveau type de ressource devrait être implémenté.

                Cela dit, c'est peut être pour ça que mon code parait compliqué.

                Merci en tout cas pour vos réponses, désolé pour le temps que je prends à répondre.

                • Partager sur Facebook
                • Partager sur Twitter
                  10 mars 2020 à 17:14:21

                  yoyo22 a écrit:

                  > je veux pouvoir extraire de ma liste de Type "Ressource" seulement les ressources d'un certain type, comme le "Bois" par exemple.

                  > Je ne vois pas comment avoir un code bien optimisé en objet sans avoir recours à l'héritage.

                  > Et je ne me vois pas avoir une liste de ressource de chaque type pour chaque zone, ce qui m'obligerait à initialiser une nouvelle liste si un nouveau type de ressource devrait être implémenté.

                  Bon, prenons les exemples idiots. Admettons que tu gères le matériel d'un aeroport. Dedans il y des véhicules qui sont des avions et des camions.

                  On va dire que, comme ils ont des trucs en commun (marque, constructeur, etc) il y a un héritage dpuis la classe véhicule. Ok.

                  Maintenant, dans ton aeroport, tu n'as pas du tout l'intention de demander les mêmes actions aux avions (se preparer à décoller)  et aux camions (déposer un chargement).

                  Donc tu n'as aucun intérêt à tout coller dans une collection fourre-tout, pour après te demander, ah tiens, de quel type il est ce truc pour voir si je peux lui demander d'exécuter l'opération qu'il est le seul à connaitre.

                  Parce que ton objection "ça m'obligerait à déclarer une liste pour chaque type" se transforme en "ça m'oblige à écrire du code pour tester chacun des types".  Si ton code il doit séparer les ressources par type, et donc tu dois le changer quand tu ajoutes un type. Tu perds le polymorphisme, et tu te compliques la vie.

                  -
                  Edité par michelbillaud 10 mars 2020 à 17:15:05

                  • Partager sur Facebook
                  • Partager sur Twitter
                    10 mars 2020 à 17:52:08

                    Oui je suis d'accord avec toi, mais imagines que dans le projet l'aéroport n'est qu'un sous élément. Si un beau jour, on a des tank dans les aéroports, au lieu de simplement ajouter la classe tank qui hérite de véhicule, je devrai en plus ajouter une liste "tank" à aéroport, et éventuellement à "Banque", si les banques ont aussi des véhicules de type tank. 

                    Si il est possible d'avoir une simple liste véhicule, je n'ai pas besoin de mettre à jour toutes les classes qui l'utilisent à chaque fois qu'un nouveau véhicule est disponible.

                    Et il me semble qu'en cours de design pattern, c'est ce qu'on apprenait, utiliser une liste de type interface pour avoir dans cette liste tous nos différents objets. Ca limite les liste, et le code, donc c'est plus propre il me semble.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      10 mars 2020 à 18:21:27

                      Manipuler une liste d'un type plus générique ça sert que quand on se soucie uniquement des opérations communes à ses éléments.

                      Après dans le cas en question faudrait voir ce qu'on fait vraiment avec ces différentes ressources (globalement et selon leur type réel) pour pouvoir définir quelque chose d'adapté.

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Censément, quelqu'un de sensé est censé s'exprimer sensément.
                        10 mars 2020 à 19:35:51

                        Je ne vois pas en quoi votre exemple montre l'impérieuse nécessité d'avoir un liste "fourre-tout".

                        Dans votre classe "Zone", qu'est-ce qui vous empêche d'avoir autant de liste que de types de ressources (en attendant d'utiliser des Entity dans un modèle ECS), ou de "classe" (au sens cladistique, POO) de ressources distinguables par la classe "Zone" ?

                        Rien.

                        Si t'as besoin d'une liste de ressources génériques, qu'est-ce qui empêche la classe "Zone" de fournir une API pour fournir cette liste par concaténation de ces listes internes ?

                        Rien.

                        Avec une liste par "catégorie" de ressource, la classe Zone sera bien plus facilement utilisable qu'avec c'est horreur de filtrage par type dynamique.

                        >J'aimerais pouvoir avoir par zone ... mère principale, "Ressource".

                        Qu'est-ce qui t'en empêche ? Suffit que cela la classe implémente dans une de ces propriété une interface de liste de Ressources (en lecture seule, évidemment).

                        >qui est que je veux pouvoir extraire de ma liste de Type "Ressource" seulement les ressources d'un certain type

                        Faux problème, car, en ne mélangeant pas en interne ces ressources, la classe "Zone" est tout à fait à même de rendre ce service de "filtrage", en ayant les propriétés adéquates, directement en champ, ou en faisant les mêmes astuces que pour la liste des ressources.

                        Ta manière de penser te mets des œillères.

                        >comment avoir un code bien optimisé en objet

                        Certains pensent que c'est un oxymore.

                        >sans avoir recours à l'héritage.

                        Que l'héritage n'est pas un truc pour l'optimisation, ça, c'est certain.

                        Bref, très mauvais argumentaire. La POO optimise, intrinsèquement, la conception et la maintenance du code, et c'est déjà pas mal.

                        >Et je ne me vois pas avoir une liste de ressource de chaque type pour chaque zone,

                        Why ?

                        Si tu veux, un dictionnaire comme champ en interne, si tu veux économisez 3 francs 6 sous de mémoires, avec comme clé, le type de ressources.

                        Encore rien d'impossible, et rien qui oblige à saloper le code utilisateur de la classe Zone.

                        J'ai toujours du mal à comprendre l'utilité d'isoler chaque "ressource" dans une liste, une simple valeur suffirait dans la majorité des RTS.

                        >ce qui m'obligerait à initialiser une nouvelle liste si un nouveau type de ressource devrait être implémenté.

                        Non, cf. l'usage d'un dictionnaire et comme une Instance de zone n'a pas à distinguer une ressource "Bois Qui Pousse Normalement" d'un "Bois qui Pousse Par La Magie De Gandalf Le Gris", j'ai juste besoin d'une liste de "Bois" et pas pour chaque classe que l'esprit d'un GameDesign peut imaginer.

                        >Cela dit, c'est peut être pour ça que mon code parait compliqué.

                        Les œillères, c'est jamais bon pour la simplicité du code.

                        >Si un beau jour, on a des tank dans les aéroports

                        Idem, si l’aéroport traite les tanks comme des camions, ils seront dans la liste des camion.

                        S'il les traite différemment, l'aéroport mettra dans la liste correspond à la manière dont l'aéroport traite un tank (que cela soit un T52 ou un M1 Abrams).

                        >je devrai en plus ajouter une liste "tank" à aéroport

                        Non, s'il est traité par l'aéroport comme un véhicule, il sera dans la liste des véhicules, rien de plus.

                        >et éventuellement à "Banque",...

                        Idem

                        >Ca limite les liste, et le code, donc c'est plus propre il me semble.

                        C'est pas pour limiter le nombre de liste mais le code IDENTIQUE.

                        Si votre code est différent pour chaque type potentiellement dans la liste, vous avez tout perdu et fait une usine à gaz.

                        Il ne faut pas appliquer les DP aveuglement.

                        Les cas d'usage de ceux-ci sont très importants.

                        • Partager sur Facebook
                        • Partager sur Twitter
                        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                          10 mars 2020 à 21:37:46

                          yoyo22 a écrit:

                          Oui je suis d'accord avec toi, mais imagines que dans le projet l'aéroport n'est qu'un sous élément. Si un beau jour, on a des tank dans les aéroports, au lieu de simplement ajouter la classe tank qui hérite de véhicule, je devrai en plus ajouter une liste "tank" à aéroport, et éventuellement à "Banque", si les banques ont aussi des véhicules de type tank. 

                          Si il est possible d'avoir une simple liste véhicule, je n'ai pas besoin de mettre à jour toutes les classes qui l'utilisent à chaque fois qu'un nouveau véhicule est disponible.

                          En fait si un jour il faut des tanks, si l'accès aux tanks nécessite du code spécifique, ça sera même plus facile des les isoler dans une liste spécifique List<Tank>.

                          Par contre s'ils ne nécessitent pas plus de code spécifique que les camions, alors ils peuvent être dans une List<Camion> qui gère des objets dont le comportement est identique. Donc, le problème de devoir rajouter du code, c'est un faux problème...

                          • Partager sur Facebook
                          • Partager sur Twitter

                          foreach( B in list<A>) avec B héritant de A

                          × 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