Pregunta 1¿Cuál de las siguientes es la forma correcta de hacer que Dog herede de Animal?
Herencia de clases — Reutilizar funciones de una clase existente
Aprende la herencia de clases en Python. Hereda atributos y métodos con class Hijo(Padre):, sobrescribe métodos y llama a la versión del padre con super() — todo con diagramas.
La última vez usamos métodos especiales como __add__ y __str__ para enseñar operaciones nativas a nuestras propias clases. Esta vez cubrimos una de las ideas centrales de la POO: la herencia de clases.
¿Por qué usar la herencia?
Cuando construyes apps, te encuentras a menudo con clases casi iguales pero que difieren en algunos puntos. Imagina Customer, Employee y Admin — todas tienen un name y un email y devuelven un greeting(), pero cada una tiene unos cuantos atributos o métodos extra.
Podrías escribir los mismos name / email / greeting() en las tres clases — pero el código quedaría duplicado y cada cambio tendría que hacerse en tres lugares. La solución limpia es poner las partes compartidas en una clase padre y hacer que cada clase hija «herede del padre y solo escriba las diferencias». Eso es la herencia.
Person). Solo las diferencias van en el hijo (Employee). No hace falta volver a declarar name o greeting cada vez.Heredar de un padre — class Hijo(Padre):
La sintaxis es simple: cuando defines una subclase, pon la clase padre entre paréntesis después del nombre de la clase. La subclase recoge automáticamente todos los atributos y métodos del padre.
Abajo, Person es el padre (con name, age y un greeting) y Employee es el hijo. Employee no define ni un solo método propio, pero llamar a greeting() simplemente funciona gracias a la herencia.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greeting(self):
print(f"Hola, {self.name}")
def say_age(self):
print(f"{self.age} años")
class Employee(Person): # hereda de Person
pass # el cuerpo puede estar vacío
e = Employee("Ana", 45)
e.greeting() # Hola, Ana <- método del padre
e.say_age() # 45 años
- Atributos: name / age
- Métodos: greeting() / say_age()
- __init__(self, name, age)
- El cuerpo está vacío (solo pass)
- → Hereda atributos y métodos del padre
- Employee("Ana", 45) llama al __init__ del padre
Sobrescritura de métodos — Reemplazar con el mismo nombre
Solo herencia te da el comportamiento del padre sin cambios. Pero si escribes un método con el mismo nombre en la clase hija, la versión del hijo tiene prioridad. Eso es una sobrescritura (override).
Por ejemplo, para darle a Employee un saludo diferente como «Hola, Empleado Ana», redefine greeting en el hijo. Llamarlo en una instancia de Person da el saludo del padre; llamarlo en una instancia de Employee da el del hijo. El comportamiento cambia según a qué clase pertenece la instancia que llama.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greeting(self):
print(f"Hola, {self.name}")
class Employee(Person):
def greeting(self): # mismo nombre = sobrescritura
print(f"Hola, Empleado {self.name}")
p = Person("Carlos", 30)
e = Employee("Ana", 45)
p.greeting() # Hola, Carlos
e.greeting() # Hola, Empleado Ana <- gana la versión del hijo
super() — Llamar al método del padre
A veces quieres sobrescribir un método pero seguir basándote en el comportamiento del padre. Ahí entra super(). Escribir super().method() llama al método del mismo nombre en el padre de la clase actual.
Por ejemplo, supón que quieres «el greeting del padre (que imprime Hola, Ana) seguido de una línea extra en el hijo». Dentro del greeting del hijo, llama primero a super().greeting() y luego añade tu propia línea.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greeting(self):
print(f"Hola, {self.name}")
class Employee(Person):
def greeting(self):
super().greeting() # ① ejecuta primero el greeting del padre
print(f"Soy Empleado {self.name}") # ② luego la línea propia del hijo
Employee("Ana", 45).greeting()
# Hola, Ana
# Soy Empleado Ana
greeting del hijo, llamar a super().greeting() ejecuta el greeting del padre directamente. self se pasa automáticamente — no lo escribes.Sobrescribir __init__ para añadir más atributos
Donde super() brilla más es cuando sobrescribes __init__. Imagina que la clase hija necesita los atributos del padre más algunos propios — por ejemplo, Employee también debería llevar un phone_number.
En ese caso redefines __init__ en el hijo, pero la inicialización del padre (self.name = name etc.) se gestiona en una línea con super().__init__(name, age), y añades los atributos extra después. Así no tienes que repetir las asignaciones de name / age.
Employee(...) ejecuta el __init__ del hijo → super().__init__(name, age) deja que el padre asigne name / age → luego el hijo añade phone_number. Estado final: atributos padre + hijo todos en su lugar.class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Employee(Person):
def __init__(self, name, age, phone_number):
super().__init__(name, age) # ① el padre define name / age
self.phone_number = phone_number # ② añade el atributo solo del hijo
def show(self):
print(f"{self.name} / {self.age} / {self.phone_number}")
Employee("Ana", 45, "555-1111").show()
# Ana / 45 / 555-1111
Olvida super().__init__(...) y los atributos desaparecen
Si sobrescribes __init__ pero olvidas llamar a super().__init__(...), las asignaciones del padre como self.name = name nunca ocurren. La próxima vez que leas self.name, obtienes un AttributeError. Cada vez que sobrescribes __init__ en una clase hija, llama a super().__init__(...) justo arriba — hazlo costumbre.
Verificación de conocimientos
Responde cada pregunta una a una.
Pregunta 2¿Cuál es la descripción más precisa de la sobrescritura de método?
Pregunta 3Si olvidas llamar a super().__init__(...) en el __init__ del hijo, ¿qué pasa?