IIC2233-2015-2 / syllabus

Página principal del curso
48 stars 57 forks source link

[Examen] Multi-herencia #524

Closed andresespinosapc closed 8 years ago

andresespinosapc commented 8 years ago

En el material de Herencia-Multiherencia hay un ejemplo en el que una clase hereda de otras 2, cada una con un método llamar, y al hacer super().llamar() se llama al método de las 2 clases heredadas. Hice un par de pruebas y hay algo que no entiendo.

class Hola:

    def __init__(self):
        super().__init__()
        print('hola')

class Chao:

    def __init__(self):
        super().__init__()
        print('chao')

class Mix(Hola, Chao):

    def __init__(self):
        super().__init__()
        print('mix')

m = Mix()

El código anterior funciona perfectamente, imprimiendo

chao
hola
mix

El Problema es que cuando quito el super.__init__() de las clases Hola y Chao solo imprime las 2 últimas líneas, es decir nunca se llama al init de Chao. No entiendo por qué pasa esto, en qué influye ese cambio?

bcsaldias commented 8 years ago

Porque solo se llama al inicializador de la primera clase de la que se hereda, y así con cualquier método. Verifica que al cambiar de orden (Chao, Hola) entonces se imprimirá chao, esto es porque hay predominancia en los métodos.

Revisa también el caso del diamante, ahí se explica bien eso.

Saludos

Nota de aaossa: Me voy a colar. Esto es algo que encontré que podría responder a tu pregunta. En el ejemplo tenemos que Mix() llama primero a Hola.__init__ (Python busca de izquierda a derecha) y si no tiene __init__, sigue con Chao.__init__. Como dijo Belén, si cambias el orden debería imprimir primero chao y después mix. También deberías probar quitando el __init__ de una de las clases y ver que pasa.

andresespinosapc commented 8 years ago

Ya entendí. Gracias !

El 1 de diciembre de 2015, 20:32, Belén Saldías notifications@github.com escribió:

Porque solo se llama al inicializador de la primera clase de la que se hereda, y así con cualquier método. Verifica que al cambiar de orden (Chao, Hola) entonces se imprimirá chao, esto es porque hay predominancia en los métodos.

Revisa también el caso del diamante, ahí se explica bien eso.

Saludos

— Reply to this email directly or view it on GitHub https://github.com/IIC2233-2015-2/syllabus/issues/524#issuecomment-161131190 .

Andrés Espinosa Estudiante Ingeniería UC

AntoniaMendoza commented 8 years ago

Yo quisiera saber por qué esto falla:


class Hola:

    def __init__(self):
        super().__init__()
        print('hola')

class Chao(Hola):

    def __init__(self):
        super().__init__()
        print('chao')

class Mix(Hola, Chao):

    def __init__(self):
        super().__init__()
        print('mix')

m = Mix()

Al final la última vez que se llama a Hola dentro de Chao, Hola no debiese llamar en super() a object? En ningún caso me deja repetir dos veces una misma clase. ¿Será porque el "hola" anterior no ha terminado de construir? Si ese Hola del que hereda Chao fuese otra clase, sí me funciona

lopezjurip commented 8 years ago

Yo creo que el problema ahí es que Chao ya es Hola.

Un ejemplo más real: class Animal: ... class Mamifero(Animal): ... class Perro(Animal, Mamifero): ... No tiene sentido que yo diga que Perro hereda de Animal y Mamifero, puesto que por ser mamífero ya es animal, no puede existir un mamífero no animal.

AntoniaMendoza commented 8 years ago

Mamifero hace overriding de metodos de Animal que yo deseo tener pero como están escritos en Animal. Además quiero tener cosas específicas de Mamífero. No soy ni animal ni soy mamifero, pero comparto cosas de los dos. ¿Escribo todo el código de nuevo?

MainScientist commented 8 years ago

Probablemente las cosas que quieras tener de mamifero puedan separarse de mamifero y hacer una nueva clase, por ejemplo:

class Animal: ... class Vertebrado(Animal): ... class Mamifero(Vertebrado): ... class Reptil(Vertebrado): ...

En este caso Reptil tiene cosas de Vertebrado que tambien tiene Mamifero y cosas de Animal (todo lo que no fue sobre escrito en Vertebrado). Nunca escatimes en clases, mientras mas clases tengas tu codigo es mas legible, mas manipulable y mas extensible a futuro. Heredar de dos clases que por si solas representan un objeto no es tan buena idea, quizas el mejor approach para usar multiherencia es tener una clase base y que las demas sean interfaces, pero eso ya es otro tema aparte.

lopezjurip commented 8 years ago

No soy ni animal ni soy mamifero, pero comparto cosas de los dos.

Es que en tal caso no tiene sentido usar herencia :/, si bien ayuda a reducir código, la idea es que sea una manera "jerárquica natural" de ordenar y modelar un problema.

De ser así, sería mejor usar Composición

Ahora si de verdad quieres acceder al método del padre del padre. No sé si esto en Python funcione, pero en otros lenguajes sí:

class Animal:
  def metodo(self):
   pass

class Mamifero(Animal):
  def metodo(self):
   pass

class Perro(Mamifero):
  def metodo(self):
   return super().super().metodo()