CON · Concepto 8 · Programación orientada a objetos

39.Herencia

Crear una clase nueva a partir de otra existente, para que herede sus atributos y métodos y solo agregue o cambie lo que la hace distinta.

¿Qué es?

La herencia permite crear una clase hija a partir de una clase padre: la hija recibe automáticamente todos los atributos y métodos del padre, y solo agrega o cambia lo que la hace diferente.

En una escuela hay alumnos y docentes. Los dos son personas: tienen nombre y correo y se pueden presentar. Además, el alumno tiene grupo y el docente tiene materias. En lugar de repetir lo común, se escribe una vez en Persona y las otras clases lo heredan.

        Persona
     (nombre, correo, presentarse)
        /          \
   Alumno          Docente
  (+ grupo)      (+ materias)

La prueba para saber si conviene heredar es la frase «es un»: un alumno es una persona ✔; un salón es un alumno ✘.

Sintaxis (pseudocódigo / Python)

Pseudocódigo de diseño (no ejecutable en PSeInt)

Clase Persona
	Atributos: nombre
	Metodo presentarse
FinClase

Clase Alumno hereda de Persona
	Atributos: grupo
FinClase

Python

class Persona:
    def __init__(self, nombre, correo):
        self.nombre = nombre
        self.correo = correo

    def presentarse(self):
        return f"Hola, soy {self.nombre}"

class Alumno(Persona):                       # Alumno hereda de Persona
    def __init__(self, nombre, correo, grupo):
        super().__init__(nombre, correo)     # usa el __init__ del padre
        self.grupo = grupo

    def presentarse(self):                   # sobrescribe el método
        return super().presentarse() + f", del grupo {self.grupo}"

class Docente(Persona):
    def __init__(self, nombre, correo, materias):
        super().__init__(nombre, correo)
        self.materias = materias

ana = Alumno("Ana", "ana@escuela.mx", "3A")
paco = Docente("Paco", "paco@escuela.mx", ["Redes", "Programación"])

print(ana.presentarse())
print(paco.presentarse())                    # heredado sin cambios
print(isinstance(ana, Persona))

Salida:

Hola, soy Ana, del grupo 3A
Hola, soy Paco
True
Elemento Qué hace
class Hija(Padre): Declara la herencia
super().__init__(...) Ejecuta el constructor del padre
Método con el mismo nombre Sobrescribe el del padre
isinstance(obj, Clase) Revisa si un objeto es de esa clase o de una hija

Ejemplo guiado

Problema: una tienda escolar vende productos normales y productos con descuento. Ambos tienen nombre y precio, pero el precio final se calcula distinto.

class Producto:
    def __init__(self, nombre, precio):
        self.nombre = nombre
        self.precio = precio

    def precio_final(self):
        return self.precio

    def etiqueta(self):
        return f"{self.nombre}: ${self.precio_final():.2f}"

class ProductoEnOferta(Producto):
    def __init__(self, nombre, precio, descuento):
        super().__init__(nombre, precio)
        self.descuento = descuento           # porcentaje

    def precio_final(self):
        return self.precio * (1 - self.descuento / 100)

    def etiqueta(self):
        return super().etiqueta() + f" (−{self.descuento}%)"

productos = [
    Producto("Cuaderno", 35),
    ProductoEnOferta("Calculadora", 280, 15),
    Producto("Bolígrafo", 12),
]

total = 0
for p in productos:
    print(p.etiqueta())
    total += p.precio_final()
print(f"Total: ${total:.2f}")

Salida esperada:

Cuaderno: $35.00
Calculadora: $238.00 (−15%)
Bolígrafo: $12.00
Total: $285.00

ProductoEnOferta hereda etiqueta(), pero como cambió precio_final(), la etiqueta heredada ya muestra el precio con descuento.

Errores comunes

# ✗ Incorrecto
class Persona:
    def __init__(self, nombre):
        self.nombre = nombre

class Alumno(Persona):
    def __init__(self, nombre, grupo):
        self.grupo = grupo

a = Alumno("Ana", "3A")
print(a.nombre)
AttributeError: 'Alumno' object has no attribute 'nombre'

Buenas prácticas

  • Aplica la prueba «es un» antes de heredar.
  • Pon en el padre solo lo realmente común.
  • Usa super() en lugar de escribir el nombre del padre.
  • Al sobrescribir, respeta lo que el método promete: si precio_final() devuelve un número en el padre, que también lo haga en la hija.
  • Prefiere composición cuando la relación sea «tiene un».

Material descargable

Aún no hay material descargable para este tema. Pronto habrá cuadernillos, manuales o laboratorios.

Referencias

© solutions_ · Fundamentos de programación · 39 Herencia