Otra vez la herencia múltiple

Alexis Roda alexis.roda.villalonga en gmail.com
Mie Jul 23 18:20:26 CEST 2008


En/na Beni ha escrit:
> Leyendo lo que me habeis pasado y pensando un poco...
> 
> supongo que como parece que funciona python, la signatura de los métodos
> tiene que ser igual.  Pero no veo el por que no tener constructores con
> distintos tipos de parámetros. Java los usa continuamente. Es más, son
> objetos distintos que tienen sus propias propiedades y métodos. Y si heredo
> de ellos necesitaré algún método para poder llamarlos con los parámetros que
> yo crea necesarios en el hijo.

Para decidir que método invocar Java compara el número y tipo de los 
argumentos utilizados en la llamada con los argumentos formales (número 
y tipo) de los métodos homónimos y a partir de ciertas reglas escoge el 
que mejor se ajusta. En python el tipo de los argumentos de una 
función/método no se declara, por tanto este mecanismo no es aplicable 
directamente.

En python es posible conseguir un efecto parecido utilizando *args y 
**kw y programando la función/método de forma que se comporte de manera 
diferente en función de los argumentos recibidos.

> Si no me equivoco (no domino mucho el inglés) parece que super te devuelve
> el tipo de una clase para llamar al método. Este tipo pude ser A, B, C
> dependiendo de la definición de la misma. Por tanto, como comentaba Alexis,
> deben tener la misma signatura.

No me explique bien. Quería decir que tu ejemplo no funcionaría por este 
motivo. Como bien dices, super() se limita a ofrecer un mecanismo para 
localizar el método y no sabe nada sobre los parámetros utilizados en la 
llamada.

La restricción no es tan fuerte. Más que signaturas idénticas deben 
tener signaturas compatibles. Esto puedes conseguirlo con *args, **kw 
y/o argumentos con valores por defecto.

class A(object):
     def __init__(self, nombre, *args):
         print nombre
         super(A, self).__init__(nombre, *args)

class B(object):
     def __init__(self, nombre, apellidos):
         print nombre, apellidos
         super(B, self).__init__(nombre, apellidos)

class C(A, B):
     def __init__(self):
         super(C, self).__init__("hola", "adios")

class D(B, A):
     def __init__(self):
         super(D, self).__init__("hola", "adios")

print "C (A, B) - A(nombre) - B(nombre, apellidos) >",
c = C()

print "D (B, A) - A(nombre) - B(nombre, apellidos) >",
d = D()

Aunque en mi opinión es un truco muy sucio, con más inconvenientes que 
ventajas.

> Por tanto para llamar a cada constructor necesitaré hacerlo de la forma
> antes comentada.
> class C(A, B):
>     def __init__():
>         A.__init__(self, "hola")
>         B.__init__(self, "hola", "adios")
> 
> ¿Sería correcto?

Funciona, sí y si A y B son clases dispares probablemente sea la mejor 
opción.




Saludos
_______________________________________________
Lista de correo Python-es 
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes





Más información sobre la lista de distribución Python-es