Partage
  • Partager sur Facebook
  • Partager sur Twitter

héritage bancal

Sujet résolu
    27 septembre 2014 à 19:12:16

    bonjour,

    je n'arrive pas à faire un héritage entre une classe mère Monstre et les classes filles Zombi,Troll,Orc   etc.

    c'est au moment d' instancier l'objet mon_zombi que ça plante, j'ai tout essayé et j'ai obtenu l'arc en ciel des erreurs possible : typeerror , attributeerror, __init__() missing 4 arguments etc. Même en s'inspirant d'exemples du net , je ne comprend pas !

    Il s'agit d'un code test devant servir à démouler vite fait mon premier zombi, il est prévu de changer mais comme ça bloque déjà...

    class Monstre():
    
    
    	def __init__(self,pos_y,pos_x,race,pv):
    		
    		self.__pos_y = pos_y
    		self.__pos_x = pos_x
    		self.__race = race
    		self.__pv = pv
    		
    	def spawn(self):
    		screen.addch(20,40,'Z')
    	
    	# il faudra utiliser plus tard un dico_symbol_monstre comme intermédiaire  a la place de "Z" directement (zombi)
    			
    	def die(self):
    		
    		screen.delch(self.__pos_y,self.__pos_x)
    		chr(screen.inch(self.__pos_y,self.__pos_x))==' '
    		screen.refresh 
    	
    	 
    		
    class Zombi(Monstre):
    	
    	# def __init__(self,pos_y,pos_x,race,pv):????????????
    	def __init__(self):
    		Monstre.__init__(self,self.pos_y,self.pos_x,self.race,self.pv)
    		#Monstre.__init__(self,20,40,'race_Zombi',95) ???????????
    
    
    		
    mon_zombi = Zombi()
    

    C'est la première fois que je me frotte à l'héritage 

    -
    Edité par buffalo974 27 septembre 2014 à 19:14:38

    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      27 septembre 2014 à 19:27:48

      De manière générale, si tu veux construire un objet sur le modèle de la classe mère, fait super().__init__(arguments), super est une fonction qui te donne au sein d'une classe fille la classe mère. Sinon je pense que le problème vient du fait que tu appelles Monstre.__init__ avec un argument de trop et que tu lui passe en argument des attributs inexistants. Essaie donc de remplacer ta ligne 28 par:

      super().__init__(20, 40, 'race_Zombi', 95)

       Edit: C'est HS mais "Zombi" s'écrit "Zombie" ;).

      Edit 2: Je note quand même que les '__' avant tes attributs dans Monstre.__init__ sont contraire aux règles de la POO pythonienne car, en Python, les attributs sont publics donc pas d'encapsulation à proprement parler. Et en plus ça sert pas à grand chose car un utilisateur peut très bien y accéder en tapant:

      instancedemonstre._Monstre__pos_y

      -
      Edité par Anonyme 27 septembre 2014 à 19:41:47

      • Partager sur Facebook
      • Partager sur Twitter
        27 septembre 2014 à 21:13:10

        Salut,

        Retire les self. dans tes attributs, mets les attributs ET dans ta méthode __init__ ET dans l'appel de la méthode Monstre.__init__():

        class Zombi(Monstre):
             
            def __init__(self, pos_y, pos_x, race,pv):
                Monstre.__init__(self, pos_y, pos_x, race, pv)


        Et n'oublie de placer les attributs quand tu créé l'instance:

        mon_zombi = Zombi(0, 0, "Zombie", 240)

        REMARQUE: À moins que tu veuille ajouter/surcharger des méthodes/attributs (que tu n'aurait pas montré dans ce morceau de code), l'héritage dans le cas que tu présente n'a pas d'intérêt. Tu pourrai directement faire:

        mon_zombi = Monstre(0, 0, "Zombie", 240)



        • Partager sur Facebook
        • Partager sur Twitter
        Précepte: Le mieux est l'ennemi du bien
        Anonyme
          27 septembre 2014 à 23:46:30

          Surtout qu'une variable privée n'est pas réellement une variable privée en python

          >>> class test:
          ...     def __init__(self):
          ...         self.__a = 1
          ... 
          >>> t = test()
          >>> t.__dict__
          {'_test__a': 1}
          >>> t._test__a
          1
          



          • Partager sur Facebook
          • Partager sur Twitter
            28 septembre 2014 à 4:36:52

            Voici deux sources d'inspiration de deux auteurs réputés :

            # http://fr.openclassrooms.com/forum/sujet/un-jeu-d-echec-en-console-77316
            
            class Piece(object):
                """
                Interface commune à toutes les pièces.
                Ne s'utilise pas directement.
             
                """
                def __init__(self, echiquier, couleur, symbole):
                    """
                    Construit une pièce.
                    echiquier : echiquier sur lequel se trouve la pièce
                    couleur : NOIR ou BLANC.
                    symbole : caractère symbolisant la pièce.
                     
                    """
                    self.__echiquier = echiquier
                    self.__couleur = couleur
                    self.__symbole = symbole
            
            (...)
            ###############################################################################
            # classes dérivées de Piece
             
            class Tour(Piece):
                def __init__(self, echiquier, couleur):
                    Piece.__init__(self, echiquier, couleur, SYMBOLE_TOUR)
             
            class Pion(Piece):
                def __init__(self, echiquier, couleur):
                    Piece.__init__(self, echiquier, couleur, SYMBOLE_PION)
            
            (...)
            --------------------------------------------------------------------------------
            
            # http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-5/
            
            class Arme(object):
            
                def __init__(self, nom, degat):
            
                    self.nom = nom
                    self.degat = degat
            
                def attaque(self, cible): # on retire les degâts de l'épee des points de vie
                    cible.vie -= self.degat
            
            
            class Protection(object):
            
                def __init__(self, nom, armure):
            
                    self.nom = nom
                    self.armure = armure
            
                def defend(self, degat): # on diminue les degâts, voire on les annule
            
                    degat = degat - self.armure
                    if degat < 0:
                        return 0
            
                    return degat
            
            >>> epee = Arme('Epée Mana', degat=999)
            >>> casque = Protection('Casque de Balduran', armure=1)
            (...)
            
            class ProtectionOffensive(Arme, Protection):
            
                def __init__(self, nom, degat, armure):
            
                    Arme.__init__(self, nom, degat) # appelle le __init__ de arme
                    Protection.__init__(self, nom, armure) # appelle le __init de protection
            
                    # comme on a appelé les deux __init__, on va avoir les attributs
                    # settés dans les deux __init__ attachés à cette classe
            
            >>> bouclier = ProtectionOffensive('Bouclier du dragon', degat=10, armure=100)
            >>> bouclier.degat
            10
            >>> bouclier.armure
            100
            >>> bouclier.defend(10)
            0

            En fait , je voudrai disposer d'un réservoir de monstres ( liste, ou dico, ou liste couplée avec un dico; voire une bdd sqlite sur une version top finale). Cependant les monstres ne doivent pas apparaître tout d'un coup au démarrage, mais de façon "exponentielle" de façon à mettre une pression progressive et que le joueur ne s'attarde pas trop dans un niveau.

            La classe Monstre dirait que chaque creature possède une jauge de vie,des points d'attaques etc. et définirait les méthodes taper() , fuir()...

            Puis les classes filles Zombi,Troll,Vampire etc. donneraient le montant précis de chaque attribut , ainsi que des méthodes uniques telle que

            hypnotiser() pour le vampire : fige (x,y) du joueur pendant 2 tours par exemple.

            • Partager sur Facebook
            • Partager sur Twitter
              28 septembre 2014 à 10:21:39

              Ça m'a l'air très intéressant comme projet :)

              Qu'est-ce que tu entends pas "réservoir de monstres"? Si c'est de créer à l'avance un certain nombre de zombies, vampires, etc... je dirai que ce n'est pas la meilleure façon de faire.

              Bon, ça va dépendre énormément de comment tu gère ton projet. Tu pourrais par exemple mettre les infos pour les monstres de base en valeur par défaut de tes classes:

              class Vampire(Monstre):
                    
                  def __init__(self, pos_y=0, pos_x=0, race="vampire exilé",pv=240):
                      Monstre.__init__(self, pos_y, pos_x, race, pv)



              Et pour un boss, le faire hériter d'une classe fille:

              class Dracula(Vampire):
                    
                  def __init__(self, pos_y=5, pos_x=5, race="Comte Dracula",pv=10000):
                      Vampire.__init__(self, pos_y, pos_x, race, pv)



              Et si tu préfère stocker tes monstres dans un conteneur, tu peux utiliser un tuple:

              #Tuples qui stockent les classes
              monstres = (Loup-Garou, Vampire, Zombie)
              boss = (Dracula, Frankenstein)
              hero = (VanHelsing,)
              
              #Pour les appeler:
              monstres[1]()
              monstres[1](3)  #en pos_y=3
              monstres[1](pos_y=3, pos_x=1)
              monstres[1](pv=300)

              -
              Edité par Olygrim 28 septembre 2014 à 15:56:31

              • Partager sur Facebook
              • Partager sur Twitter
              Précepte: Le mieux est l'ennemi du bien
              Anonyme
                28 septembre 2014 à 10:42:18

                Certes des personnes réputées utilisent ce style de programmation, car en général ils viennent d'un langage comme le C++ ou le java.

                Mais des auteurs comme Van Rossum ou Martelli quand à eux ne sont pas pour... à moins de les utiliser pour éviter les collisions de noms de variables entre les classes filles et leur classe mère. C'est pas pour rien que par mon exemple on peut en faisant un effort y accéder, car en modifiant ce nom de variable, on évite cette collision. En gros cette variable reste privée mais est protégée de toute modification car en réalité elle n'est pas nommée comme on le croit.

                Bref la variable privée est conseillée que pour les frustrés de langage tel le C++/Java/... où les variables privées sont indispensables. En python ce n'est pas le cas, on laisse totale liberté et responsabilité au programmeur.

                Ensuite pour ton problème de zombi, en fait 

                class Zombi(Monstre):
                    def __init__(self):
                        Monstre.__init__(self,20,40,'race_Zombi',95)

                doit fonctionner ? Quel est le problème en fait ?

                ou alors...

                class Zombi(Monstre):
                    def __init__(self, pos_y, pos_x, race, pv):
                        Monstre.__init__(self, pos_y, pos_x, race, pv)
                 
                 
                         
                mon_zombi = Zombi(20,40,'race_Zombi',95)

                Je connais pas ta façon de concevoir, mais j'aurais tendance à conseiller la 1ère.




                • Partager sur Facebook
                • Partager sur Twitter
                  28 septembre 2014 à 14:25:52

                  merci à tous , je vais essayer toutes vos astuces pour voir laquelle s'imbrique le mieux avec ce que j'ai déjà.:)

                  • Partager sur Facebook
                  • Partager sur Twitter
                    21 décembre 2014 à 21:35:38

                    Salut,

                    je reviens sur ce post car on n'y a pas parlé de super().

                    Comment l' utiliser ici pour Dracula cité plus haut (fille de Vampire elle meme fille de Monstre)  et quel serait son

                    avantage ?

                    -
                    Edité par buffalo974 21 décembre 2014 à 21:37:58

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Anonyme
                      21 décembre 2014 à 22:08:46

                      Bin tout simplement comme ça:

                      class Dracula(Vampire):
                      
                      def __init__(self, pos_y, pos_x, pv=10000):
                          super(Dracula, self).__init__(pos_y, pos_x, 'Comte Dracula', pv)
                      
                      </pre> Note: en Python 3 tu peux te passer des arguments passés à super, mais il est préférable de les spécifier tout de même pour que le code soit portable. Sinon je ne connaît pas les avantages de super, cette fonction renvoie juste l'objet self en tant qu'instance de sa classe mère. Edit: je viens de trouver ça: http://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods

                      -
                      Edité par Anonyme 21 décembre 2014 à 22:16:57

                      • Partager sur Facebook
                      • Partager sur Twitter

                      héritage bancal

                      × 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