2009-04-27 15 views
5

El proceso de inicialización de un grupo de clases que comparten un elemento primario común se puede dividir en tres partes: parte común1, parte de clase específica, parte común2. Actualmente las dos primeras partes se llama desde la función __init__ de cada clase hija, pero la segunda parte común tiene que ser llamado por separado Por ejemplo:¿Cómo realizar tareas comunes posteriores a la inicialización en clases heredadas de Python?

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 

¿Hay una manera de no tener que llamar finalizeInitialization() ?

EDITAR uno puede transferir la llamada a finalizeInitialization() en __init__ de Subclass1 (como en S.Lott's answer). Esto hace la vida más fácil, pero aún hay que recordar completar la inicialización, esta vez dentro del "constructor". De cualquier manera, no hay forma de forzar la inicialización completa, que es lo que estoy buscando.

Respuesta

6

Versión 1: delegue todo.

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

Versión 2 - delegado sólo un paso

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

Gracias, pero vea mi edición para obtener una aclaración –

+0

Tomo la versión 2. Gracias –

0

¿Qué hay de malo en llamar finalInitilazation desde init de la subclase?

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 tiene que llamar a varios métodos en un orden específico que por lo general significa que el diseño tiene problemas para empezar (que hay un escape detalle de implementación). Entonces trataría de trabajar desde ese extremo.

Por otro lado, si las personas derivan de la clase y tienen que modificar la inicialización, deben tener en cuenta las implicaciones; no es algo que desee tener en su API normal. De forma alternativa, podría estar a la defensiva con respecto a la inicialización final y verificar que ha sido invocada en métodos que dependen de ella (llamarla o generar una excepción si no es así).

10

plantilla Método Patrón de diseño al rescate:

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

Al igual que en el enfoque de S. Lott, excepto que no hay manera (abreviatura de anular __init__) para las clases derivadas para anular (o incluso llaman) los métodos comunes :

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" 

es posible que desee para proporcionar una implementación por defecto de specific en BaseClass si no está bien para levantar un AttributeError cuando se crea una instancia de cualquier subclase que no lo hace proporcionar su propia implementación.

Cuestiones relacionadas