Herencia y Polimorfismo en Python
La herencia permite crear nuevas clases basadas en clases existentes, reutilizando y extendiendo su funcionalidad. El polimorfismo permite que objetos de diferentes clases respondan al mismo metodo de maneras distintas.
Herencia basicaclass Animal:
def __init__(self, nombre, especie):
self.nombre = nombre
self.especie = especie
self.energia = 100
def comer(self, alimento):
self.energia += 20
print(f'{self.nombre} come {alimento}. Energia: {self.energia}')
def dormir(self):
self.energia += 30
print(f'{self.nombre} duerme. Energia: {self.energia}')
def hacer_sonido(self):
print('...')
class Perro(Animal): # Hereda de Animal
def __init__(self, nombre, raza):
super().__init__(nombre, 'Canis lupus familiaris')
self.raza = raza
def hacer_sonido(self): # Sobreescribe metodo
print(f'{self.nombre} dice: Guau guau!')
def traer_pelota(self): # Nuevo metodo
print(f'{self.nombre} trae la pelota!')
class Gato(Animal):
def __init__(self, nombre, es_interior=True):
super().__init__(nombre, 'Felis catus')
self.es_interior = es_interior
def hacer_sonido(self):
print(f'{self.nombre} dice: Miau')
def ronronear(self):
print(f'{self.nombre} ronronea...')
perro = Perro('Rex', 'Labrador')
gato = Gato('Michi')
perro.comer('croquetas') # Heredado de Animal
perro.hacer_sonido() # Sobreescrito en Perro
perro.traer_pelota() # Propio de Perro
gato.hacer_sonido()
gato.dormir() # Heredado de Animal
La funcion super()
class Vehiculo:
def __init__(self, marca, modelo, anio):
self.marca = marca
self.modelo = modelo
self.anio = anio
def info(self):
return f'{self.anio} {self.marca} {self.modelo}'
class Coche(Vehiculo):
def __init__(self, marca, modelo, anio, puertas=4):
super().__init__(marca, modelo, anio)
self.puertas = puertas
def info(self):
base = super().info()
return f'{base} ({self.puertas} puertas)'
class CocheElectrico(Coche):
def __init__(self, marca, modelo, anio, bateria_kwh):
super().__init__(marca, modelo, anio)
self.bateria_kwh = bateria_kwh
self.carga = 100
def info(self):
base = super().info()
return f'{base} - Electrico ({self.bateria_kwh} kWh)'
def cargar(self, porcentaje):
self.carga = min(100, self.carga + porcentaje)
print(f'Cargando... Bateria al {self.carga}%')
v = Vehiculo('Generic', 'Model', 2020)
c = Coche('Toyota', 'Corolla', 2023)
e = CocheElectrico('Tesla', 'Model 3', 2024, 75)
print(v.info())
print(c.info())
print(e.info())
Polimorfismo
El mismo metodo, diferentes comportamientos segun el objeto:
class Forma:
def area(self):
raise NotImplementedError('Implementar en subclase')
def describir(self):
print(f'Soy {type(self).__name__}')
print(f'Area: {self.area():.2f}')
class Rectangulo(Forma):
def __init__(self, base, altura):
self.base = base
self.altura = altura
def area(self):
return self.base * self.altura
class Circulo(Forma):
PI = 3.14159265358979
def __init__(self, radio):
self.radio = radio
def area(self):
return self.PI * self.radio ** 2
class Triangulo(Forma):
def __init__(self, base, altura):
self.base = base
self.altura = altura
def area(self):
return (self.base * self.altura) / 2
formas = [Rectangulo(10, 5), Circulo(7), Triangulo(6, 4)]
for forma in formas:
forma.describir()
area_total = sum(f.area() for f in formas)
print(f'Area total: {area_total:.2f}')
Clases abstractas
from abc import ABC, abstractmethod
class DispositivoPago(ABC):
@abstractmethod
def cobrar(self, monto):
pass
@abstractmethod
def reembolsar(self, monto):
pass
def generar_recibo(self, monto, tipo):
print(f'Recibo: {tipo} de {monto}')
class TarjetaCredito(DispositivoPago):
def __init__(self, numero, limite):
self.numero = numero[-4:]
self.limite = limite
self.usado = 0
def cobrar(self, monto):
if self.usado + monto > self.limite:
raise ValueError('Limite excedido')
self.usado += monto
self.generar_recibo(monto, 'Cargo a tarjeta')
def reembolsar(self, monto):
self.usado -= monto
self.generar_recibo(monto, 'Reembolso a tarjeta')
class Paypal(DispositivoPago):
def __init__(self, email, saldo):
self.email = email
self.saldo = saldo
def cobrar(self, monto):
if monto > self.saldo:
raise ValueError('Saldo insuficiente')
self.saldo -= monto
self.generar_recibo(monto, 'Cargo PayPal')
def reembolsar(self, monto):
self.saldo += monto
self.generar_recibo(monto, 'Reembolso PayPal')
def procesar_compra(dispositivo, monto):
try:
dispositivo.cobrar(monto)
print(f'Compra de {monto} procesada')
except ValueError as e:
print(f'Error: {e}')
tarjeta = TarjetaCredito('4532123456789012', 5000)
paypal = Paypal('[email protected]', 300)
procesar_compra(tarjeta, 150)
procesar_compra(paypal, 200)
procesar_compra(paypal, 500) # Error
Herencia multiple
class Nadador:
def nadar(self):
print(f'{self.nombre} nada')
class Corredor:
def correr(self):
print(f'{self.nombre} corre')
class Triathleta(Nadador, Corredor):
def __init__(self, nombre):
self.nombre = nombre
def competir(self):
self.nadar()
self.correr()
print(f'{self.nombre} cruza la meta!')
atleta = Triathleta('Ana')
atleta.competir()
💡 Concepto Clave
Revisemos los puntos más importantes de esta lección antes de continuar.
Resumen
- La herencia crea clases basadas en otras, reutilizando codigo
- super() llama metodos de la clase padre
- El polimorfismo permite diferentes comportamientos con el mismo metodo
- Las clases abstractas (ABC) obligan a implementar ciertos metodos
- Python soporta herencia multiple
En la proxima leccion: metodos especiales.
🧠Pon a prueba tu conocimiento
¿Cuál es el aspecto más importante que aprendiste en esta lección?
- Comprendo el concepto principal y puedo explicarlo con mis palabras
- Entiendo cómo aplicarlo en mi situación especÃfica
- Necesito repasar algunas partes antes de continuar
- Quiero ver más ejemplos prácticos del tema
✅ ¡Excelente! Continúa con la siguiente lección para profundizar más.