Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duda llamado método mismo nombre distintas clases (multiherencia) #104

Open
5 tasks done
panchouc opened this issue Aug 30, 2022 · 2 comments
Open
5 tasks done

Duda llamado método mismo nombre distintas clases (multiherencia) #104

panchouc opened this issue Aug 30, 2022 · 2 comments
Assignees
Labels
Contenidos Dudas sobre contenidos Resuelto

Comments

@panchouc
Copy link

Prerrequisitos

(Marcar colocando una X entre los corchetes los ítems que ya hiciste, así: "[X]")

  • Leí las reglas del foro (Instalación py 3.11.X con X>=7 Syllabus#1).
  • Busqué en las issues si ya preguntaron mi duda y no encontré nada parecido (https://github.com/IIC2233/syllabus/issues).
  • Mi duda no se trata de un tema administrativo o personal, ya que en ese caso debo contactar a mi profe, al Jefe de Bienestar o al correo del curso (iic2233@ing.puc.cl).
  • Utilizaré un título descriptivo y llenaré correctamente esta plantilla.
  • De ser necesario, colocaré código simple que permita explicar mi problema o duda.

Duda

¡Hola!
Tengo una duda que está relacionada a la multiherencia y polimorfismo (creo). Si por ejemplo tengo dos clases con el mismo método, llámese saludar en ambas, y tengo una tercera clase que hereda de esas dos. Si yo defino el método saludar en la clase que hereda, ¿Hay alguna forma de que pueda llamar a los métodos de saludar de las dos clases que hereda en un sólo llamado? No sé si me explico, a continuación pondré un código ejemplificando ambas situaciones.

class Ayudante:

    def saludar(self):
        print("¡Hola! Soy un ayudante")


class Academico:

    def saludar(self):
        print("¡Hola! Soy un académico")


class Doctor(Ayudante, Academico):

    def saludar(self):
        Ayudante.saludar(self)
        Academico.saludar(self)


Francisco = Doctor()
Francisco.saludar()
# ¡Hola! Soy un ayudante
# ¡Hola! Soy un académico
# Lo anterior corresponde al output

Con lo anterior logro lo que quiero, pero según lo leído y visto en clases, como que no es muy bueno llamar de forma directa a ambas clases, ya sea porque puede que se llame algo dos veces, o porque si cambia el nombre de las clases esa parte la tendría que cambiar también.

Pensé que con el método super().__init__() iba a lograr lo que quería y el código me quedaría así:

class Ayudante:

    def saludar(self):
        print("¡Hola! Soy un ayudante")


class Academico:

    def saludar(self):
        print("¡Hola! Soy un académico")


class Doctor(Ayudante, Academico):

    def saludar(self):
        super().saludar()

Francisco = Doctor()
Francisco.saludar()
# ¡Hola! Soy un ayudante
# Output

Pero en este caso solo se llama al método del ayudante, y no sigue en la jerarquía que es lo que me gustaría a mi. Me imagino que es por lo del __mro__, pero creo que debería de haber una mejor forma de llamar los métodos que tengan el mismo nombre de las superclases que lo tengan implementado, pero desconozco como hacerlo (si es que se puede hacer), para no hacer un llamado directo al nombre de las clases. Espero se haya entendido mi duda, de antemano muchas gracias por la respuesta y saludos.

@Lord-Kelsier Lord-Kelsier self-assigned this Aug 31, 2022
@Lord-Kelsier
Copy link

Hola, interesante pregunta, estuve investigando y me encontré con este hilo del cual si quieres una respuesta con ejemplos y buena explicación te recomiendo esta.

Resulta que super() sigue el MRO, en este caso el MRO seria:

(<class '__main__.Doctor'>,
<class '__main__.Ayudante'>, 
<class '__main__.Academico'>,
<class 'object'>)`

Por lo que super().saludar() desde Doctor llamaria a Ayudante.saludar() y si ayudante tiene un super() en saludar() se llamaria a Academico.saludar(). Es decir, quedaría asi:

class Ayudante:

    def saludar(self):
        super().saludar()
        print("¡Hola! Soy un ayudante")


class Academico:

    def saludar(self):
        print("¡Hola! Soy un académico")


class Doctor(Ayudante, Academico):

    def saludar(self):
        super().saludar()
Francisco = Doctor()
Francisco.saludar()
# ¡Hola! Soy un académico
# ¡Hola! Soy un ayudante
# Output -> Notar el orden

Pero esto no lo podemos dejar asi, ya que, si ejecutas:

Kelsier = Ayudante()
Kelsier.saludar()
# AttributeError: 'super' object has no attribute 'saludar'

Por lo que, para arreglarlo se puede escribir una clase abstracta que tenga el metodo saludar, pero que no haga nada quedando asi:

class Saludadores:
    def saludar(self): pass


class Ayudante(Saludadores):

    def saludar(self):
        super().saludar()
        print("¡Hola! Soy un ayudante")


class Academico(Saludadores):

    def saludar(self):
        super().saludar() # -> lo colocamos aqui por completitud
        print("¡Hola! Soy un académico")


class Doctor(Ayudante, Academico):

    def saludar(self):
        super().saludar()

Como veras, esto es bastante laborioso aun cuando saludar no lleva argumentos, pues podria pasar que tengan diferentes argumentos el saludar de academico y ayudante, por lo que aunque se puede hacer, quizas es mejor replantearte el modelamiento o hacer que tu codigo sea un poco menos mantenible al declarar explicitamente las clases

@Lord-Kelsier Lord-Kelsier added the Contenidos Dudas sobre contenidos label Aug 31, 2022
@panchouc
Copy link
Author

Buenísima! Ahí me quedó bastante claro.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Contenidos Dudas sobre contenidos Resuelto
Projects
None yet
Development

No branches or pull requests

2 participants