Solución:
Bueno, cuando se trata de herencia múltiple en general, sus clases base (desafortunadamente) deberían ser diseñado para herencia múltiple. Clases B
y C
en su ejemplo no lo son y, por lo tanto, no pudo encontrar una manera adecuada de aplicar super
en D
.
Una de las formas comunes de diseñar sus clases base para herencia múltiple es que las clases base de nivel medio acepten argumentos adicionales en sus __init__
método, que no tienen la intención de utilizar, y pasarlos a sus super
llama.
Aquí hay una forma de hacerlo en Python:
class A(object):
def __init__(self,a):
self.a=a
class B(A):
def __init__(self,b,**kw):
self.b=b
super(B,self).__init__(**kw)
class C(A):
def __init__(self,c,**kw):
self.c=c
super(C,self).__init__(**kw)
class D(B,C):
def __init__(self,a,b,c,d):
super(D,self).__init__(a=a,b=b,c=c)
self.d=d
Esto puede verse como decepcionante, pero así es.
Desafortunadamente, no hay forma de hacer que esto funcione usando super()
sin cambiar las clases base. Cualquier llamada a los constructores para B
o C
va a intentar llamar a la siguiente clase en el orden de resolución del método, que siempre será B
o C
en vez de A
clase que el B
y C
los constructores de clases asumen.
La alternativa es llamar a los constructores explícitamente sin el uso de super()
en cada clase.
class A(object):
def __init__(self, a):
object.__init__()
self.a = a
class B(A):
def __init__(self, a, b):
A.__init__(self, a)
self.b = b
class C(object):
def __init__(self, a, c):
A.__init__(self, a)
self.c = c
class D(B, C):
def __init__(self, a, b, c, d):
B.__init__(self, a, b)
C.__init__(self, a, c)
self.d = d
Todavía hay una desventaja aquí ya que el A
constructor se llamaría dos veces, lo que realmente no tiene mucho efecto en este ejemplo, pero puede causar problemas en constructores más complejos. Puede incluir una comprobación para evitar que el constructor se ejecute más de una vez.
class A(object):
def __init__(self, a):
if hasattr(self, 'a'):
return
# Normal constructor.
Algunos llamarían a esto una deficiencia de super()
, y lo es en cierto sentido, pero también es solo una deficiencia en la herencia múltiple en general. Los patrones de herencia de los diamantes suelen ser propensos a errores. Y muchas de las soluciones para ellos conducen a un código aún más confuso y propenso a errores. A veces, la mejor respuesta es intentar refactorizar su código para usar menos herencia múltiple.