2009-04-27 8 views
5

Le processus d'initialisation d'un groupe de classes partageant un parent commun peut être divisé en trois parties: partie commune1, partie spécifique à la classe, partie commune2. Actuellement, les deux premières parties sont appelées de la fonction __init__ de chaque classe enfant, mais la deuxième partie commune doit être appelé séparément Par exemple:Comment effectuer des tâches de post-initialisation courantes dans des classes Python héritées?

class BaseClass: 
    def __init__(self): 
    print 'base __init__' 
    self.common1() 

    def common1(self): 
    print 'common 1' 

    def finalizeInitialization(self): 
    print 'finalizeInitialization [common2]' 


class Subclass1(BaseClass): 
    def __init__(self): 
    BaseClass.__init__(self) 
     self.specific() 

    def specific(self): 
    print 'specific' 


if __name__ == '__main__': 
    s = Subclass1() #Don't forget to finalize the initialization 
    s.finalizeInitialization() # now the object is fully initialized 

est-il un moyen de ne pas avoir à appeler finalizeInitialization() ?

EDIT on peut transférer l'appel à finalizeInitialization() dans __init__ de Subclass1 (comme dans S.Lott's answer). Cela rend la vie plus facile, mais il faut quand même penser à terminer l'initialisation, cette fois-ci à l'intérieur du «constructeur». Dans les deux cas, il n'y a aucun moyen d'imposer une initialisation complète, ce que je recherche.

Répondre

6

Version 1 - tout déléguer.

class Subclass1(BaseClass): 
    def __init__(self): 
     super(Subclass1, self).__init__() 
     self.specific() 
     super(Subclass1, self).finalizeInitialization() 

Version 2 - délégué qu'à une étape

class BaseClass: 
    def __init__(self): 
     print 'base __init__' 
     self.common1() 
     self.specific() 
     self.finalizeInitialization() 

    def common1(self): 
     print 'common 1' 

    def finalizeInitialization(self): 
     print 'finalizeInitialization [common2]' 

    def specific(self): 
     # two choices: 
     # if this is "abstract": raise an exception 
     # if this is "concrete": pass 
+0

Merci, mais s'il vous plaît voir mon edit pour une clarification –

+0

Je prends la version 2. Merci –

0

Quel est le problème avec l'appel finalInitilazation de init de la sous-classe?

class BaseClass: 
     def __init__(self): 
      print 'base __init__' 
      self.common1() 

     def common1(self): 
      print 'common 1' 

     def finalizeInitialization(self): 
      print 'finalizeInitialization [common2]' 


    class Subclass1(BaseClass): 
     def __init__(self): 
      BaseClass.__init__(self) 
      self.specific() 
      BaseClass.finalizeInitialization(self) 

     def specific(self): 
      print 'specific' 


    if __name__ == '__main__': 
     s = Subclass1() #Don't forget to finalize the initialization 
     s.finalizeInitialization() # now the object is fully initialized 
0

Si vous devez appeler plusieurs méthodes dans un ordre spécifique, cela signifie généralement que la conception a des problèmes pour commencer (il fuit les détails de mise en œuvre). Donc, j'essaierais de travailler à partir de cette fin. D'un autre côté, si les gens dérivent de la classe et doivent modifier l'initialisation, ils doivent être conscients des implications - ce n'est pas quelque chose que vous voudriez avoir dans votre API normale. Vous pouvez également être sur la défensive à propos de l'initialisation finale et vérifier qu'elle a été appelée dans les méthodes qui en dépendent (pour l'appeler ou lever une exception si ce n'est pas le cas).

10

Modèle Modèle de conception méthode à la rescousse:

class BaseClass: 
    def __init__(self, specifics=None): 
     print 'base __init__' 
     self.common1() 
     if specifics is not None: 
      specifics() 
     self.finalizeInitialization() 

    def common1(self): 
     print 'common 1' 

    def finalizeInitialization(self): 
     print 'finalizeInitialization [common2]' 


class Subclass1(BaseClass): 
    def __init__(self): 
     BaseClass.__init__(self, self.specific) 

    def specific(self): 
     print 'specific' 
1

similaires à l'approche de S. Lott, sauf qu'il n'y a aucun moyen (court de passer outre __init__) pour les classes dérivées de passer outre (ou même appeler) les méthodes communes :

class BaseClass: 
    def __init__(self): 
     def common(): 
      print "common initialization..." 

     def final(): 
      print "common finalization..." 

     common() 
     self.specific() 
     final() 

    def final_init(self): 
     print "BaseClass.final_init" 


class Subclass1(BaseClass): 

    def specific(self): 
     print "Subclass1.specific" 

vous pouvez fournir une implémentation par défaut de specific dans BaseClass si ce n'est pas correct de soulever une AttributeError lorsque vous créez une instance d'une sous-classe qui ne fournir sa propre mise en œuvre.

Questions connexes