Herencia

Herencia simple y múltiple


La herencia es uno de los pilares fundamentales de la programación orientada a objetos. Permite crear nuevas clases basadas en clases existentes, heredando atributos y métodos. A la clase original se le conoce como clase padre o superclase, y a la clase derivada se le llama clase hija o subclase.

Este mecanismo facilita la reutilización de código y la creación de jerarquías más organizadas, siguiendo el principio DRY (Don't Repeat Yourself), que promueve evitar la duplicación innecesaria de código.

class Animal:
    def __init__(self, especie, edad):
        self.especie = especie
        self.edad = edad

    def describeme(self):
        print(f"Soy un {self.especie} y tengo {self.edad} años.")

Ahora podemos definir una subclase que hereda de Animal:

class Perro(Animal):
    pass

La clase Perro ahora posee todos los atributos y métodos de Animal, aunque no hayamos definido nada dentro de ella.

¿Por qué utilizar herencia?

La herencia permite modelar relaciones jerárquicas entre entidades. Por ejemplo, en lugar de definir múltiples clases para cada tipo de animal duplicando código, podemos centralizar lo común en una clase Animal y extenderla:

  • Evita la duplicación de código.
  • Promueve la reutilización y facilita el mantenimiento.
  • Permite extender el comportamiento de clases existentes.
Una subclase puede:
  • Heredar atributos y métodos de su clase padre.
  • Sobreescribir métodos o atributos heredados para cambiar su comportamiento.
  • Agregar nuevos atributos o métodos propios.

Herencia simple:

La herencia simple ocurre cuando una subclase hereda de una sola clase base. Sigamos con el ejemplo:

class Perro(Animal):
    def hablar(self):
        print("¡Guau!")

    def moverse(self):
        print("Camino en cuatro patas.")

También podríamos tener una clase Abeja que herede de Animal pero añada su propio comportamiento:

class Abeja(Animal):
    def hablar(self):
        print("Bzzz")

    def moverse(self):
        print("Vuelo")

    def picar(self):
        print("¡Pico con mi aguijón!")
En este caso:
  • describeme() es heredado directamente.
  • hablar() y moverse() son sobreescritos.
  • picar() es un nuevo método exclusivo de Abeja.

Herencia múltiple:

Python permite que una clase herede de más de una clase base. Esto se conoce como herencia múltiple:

class Clase1:
    def metodo(self):
        print("Método de Clase1")

class Clase2:
    def metodo(self):
        print("Método de Clase2")

class Clase3(Clase1, Clase2):
    pass

obj = Clase3()
obj.metodo()  # Salida: "Método de Clase1"

¿Por qué Clase1.metodo() y no Clase2.metodo()? Aquí entra en juego el MRO(Method Resolution Order).


MRO: Method Resolution Order

El MRO es el orden en el que Python busca métodos y atributos en las clases cuando hay herencia múltiple. Se puede consultar con:

print(Clase3.__mro__)

Esto devuelve una tupla con el orden de búsqueda. Python sigue el algoritmo C3 Linearization, y busca de izquierda a derecha.