Herencia múltiple, ABC, polimorfismo, duck typing, extensión de built-ins y dataclasses
Cerramos con herencia multinivel y múltiple, un ejemplo “bueno” de herencia, clases abstractas, polimorfismo y duck typing, cómo extender tipos incorporados, y dataclasses para datos inmutables o simples.
class SerVivo:
def info(self): return "ser vivo"
class Mamifero(SerVivo): # multinivel
def info(self): return super().info() + " → mamífero"
class Volador:
def vuela(self): return "vuela"
class Murcielago(Mamifero, Volador): # múltiple
pass
m = Murcielago()
print(m.info(), m.vuela())Nota: Orden de resolución de métodos (MRO) gobierna cómo se buscan atributos en herencia múltiple.
class Repositorio:
def guardar(self, entidad): raise NotImplementedError
class RepoEnMemoria(Repositorio):
def __init__(self): self._data = []
def guardar(self, entidad): self._data.append(entidad)
class RepoArchivo(Repositorio):
def __init__(self, ruta): self._ruta = ruta
def guardar(self, entidad): open(self._ruta, "a").write(str(entidad)+"\n")Criterio: heredar cuando hay una relación “es-un” clara y se comparte contrato (interfaz).
abc.ABC)from abc import ABC, abstractmethod
class Figura(ABC):
@abstractmethod
def area(self): ...
class Rectangulo(Figura):
def __init__(self, a, b): self.a=a; self.b=b
def area(self): return self.a * self.bBeneficio: asegurar que las subclases implementen métodos requeridos.
def imprimir_area(figura):
# Duck typing: “si tiene area(), sirve”
print("Área:", figura.area())
class Circulo:
def __init__(self, r): self.r = r
def area(self): return 3.14159 * self.r * self.r
imprimir_area(Rectangulo(2,3))
imprimir_area(Circulo(1.5))Clave en Python: el tipo estructural (métodos disponibles) prima sobre la jerarquía formal.
class ListaConSuma(list):
def suma(self):
return sum(self)
nums = ListaConSuma([1,2,3])
print(nums.suma())Advertencia: heredar de built-ins es conveniente pero considera composición si necesitas mayor control.
@dataclass)from dataclasses import dataclass
@dataclass(frozen=True) # inmutable; genera __init__, __repr__, __eq__
class Punto:
x: float
y: float
p = Punto(1.0, 2.0)
print(p) # Punto(x=1.0, y=2.0)Ventaja: menos código ceremonial para objetos de datos; frozen=True facilita inmutabilidad.
frozen=True)?