herencia-en-python

Cómo usar herencia en Python

La herencia es otro concepto importante en POO, que nos permite crear nuevas clases, basadas en otras clases existentes.

La nueva clase hereda los atributos y métodos de la clase base y puede agregar sus propios atributos y métodos. De esta forma, la subclase puede “extender” o modificar el comportamiento de la superclase.

Así, llamamos:

  • Superclase: La clase de la cual se heredan los métodos y atributos.
  • Subclase: La clase que hereda métodos y atributos de la superclase

En Python, para hacer que una clase herede de otra añadimos el nombre de la super clase entre paréntesis justo tras la definición de la clase. Así

class subclase(superclase):
   # cuerpo de subclase

Ejemplo de herencia

Vamos a verlo con una serie de ejemplos. En primer lugar, supongamos que tenemos una clase Estudiante que hereda de Persona.

# Definición de la clase Persona
class Persona:
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad
    
    def mostrar_informacion(self):
        print(f"Nombre: {self.nombre}, Edad: {self.edad}")
# Definición de la clase Estudiante que hereda de Persona
class Estudiante(Persona):
    def __init__(self, nombre, edad, nota):
        super().__init__(nombre, edad)
        self.nota = nota

# Crear una instancia de Estudiante
estudiante = Estudiante("Juan", 20, "8.7")
estudiante.mostrar_informacion()   # imprime 'Nombre: Juan, Edad: 20'

En este ejemplo,

  • Estudiante hereda de Persona usando class Estudiante(Persona)
  • La función super() se utiliza para llamar al constructor de la clase base Persona, lo que permite inicializar nombre y edad.

Sobreescritura de métodos

En este ejemplo, Estudiante sobreescribe el método mostrar_informacion de Persona.

# Definición de la clase Estudiante que hereda de Persona
class Estudiante(Persona):
    def __init__(self, nombre, edad, nota):
        super().__init__(nombre, edad)
        self.nota = nota
    
    # Sobreescribir el método mostrar_informacion
    def mostrar_informacion(self):
        print(f"Nombre: {self.nombre}, Edad: {self.edad}, Nota: {self.nota}")

# Crear una instancia de Estudiante
estudiante = Estudiante("Juan", 20, "8.7")
estudiante.mostrar_informacion()   # imprime 'Nombre: Juan, Edad: 20, Nota: 8.7'

Explicación: Aquí, Estudiante sobreescribe el método mostrar_informacion de Persona para incluir información adicional sobre la matrícula. Esto se logra definiendo un nuevo método mostrar_informacion en la clase Estudiante.

Llamar a métodos de la super clase

La clase derivada puede llamar a métodos de su clase base usando el método super(). De hecho, es habitual hacerlo con el método constructor __init__ para inicializar los atributos de la clase base.

Pero cualquier método de la clase base puede ser invocado. Vamos a verlo con un ejemplo.

# Definición de la clase Estudiante que hereda de Persona
class Estudiante(Persona):
    def __init__(self, nombre, edad, nota):
        super().__init__(nombre, edad)  # Llamada al constructor de la clase base
        self.nota = nota
    
    def mostrar_informacion(self):
        super().mostrar_informacion(self)  # Llamada a un método de la clase base
        print(f"Nota: {self.nota}")

# Crear una instancia de Estudiante
estudiante = Estudiante("Juan", 20, "8.7") # imprime 'Nombre: Juan, Edad: 20, Nota: 8.7'
estudiante.mostrar_informacion()

En este ejemplo,

  • super().__init__(nombre, edad) invoca el constructor de Persona, para inicializar los campos nombre y edad.
  • super().mostrar_informacion(self) invoca el al método mostrar_informacion de Persona, y luego añade más acciones (en el ejemplo, un print)

Herencia Múltiple

Python soporta la herencia múltiple (lo que significa que una subclase puede heredar de múltiples superclases).

Esto se logra listando las superclases entre paréntesis, después del nombre de la subclase.

class A:
    def metodo_a(self):
        print("Método de clase A")

class B:
    def metodo_b(self):
        print("Método de clase B")

class C(A, B):
    def metodo_c(self):
        print("Método de clase C")

# Creación de instancia de C y uso de métodos
objeto_c = C()
objeto_c.metodo_a()  # Salida: Método de clase A
objeto_c.metodo_b()  # Salida: Método de clase B
objeto_c.metodo_c()  # Salida: Método de clase C

En este ejemplo, la clase C hereda tanto de A como de B, permitiendo el uso de métodos definidos en ambas superclases.