目次
1. Descripción general de la herencia en Python
En Python, la herencia es un mecanismo por el cual una clase hija hereda métodos y atributos de una clase padre. Esto mejora la reutilización del código y agiliza el mantenimiento. Es uno de los conceptos clave de la programación orientada a objetos (OOP) y resulta especialmente útil en el desarrollo de sistemas a gran escala y en proyectos de larga duración.Funciones básicas de la herencia
- Reutilización de código: Una vez escrita una clase, sus funcionalidades pueden utilizarse también en otras clases, por lo que se puede evitar el código duplicado.
- Facilidad de mantenimiento: Como los cambios en la clase padre se reflejan automáticamente en las clases hijas, las correcciones y las ampliaciones de funcionalidad pueden realizarse de forma eficiente.
class ParentClass:
def greet(self):
print("Hola, soy la clase padre.")
class ChildClass(ParentClass):
def greet(self):
print("Hola, soy la clase hija.")
En este ejemplo, ChildClass
sobrescribe un método de ParentClass
. Dado que el método greet
está sobrescrito, en la clase hija se muestra un saludo propio.2. Herencia simple en Python
Herencia simple es una forma en la que una clase hija hereda funcionalidades de una única clase padre. Esta es la forma básica de herencia en Python, que permite mantener la simplicidad del código y, al mismo tiempo, ofrecer extensibilidad.Sintaxis básica y ejemplo de herencia simple
class Car:
def __init__(self, brand, color):
self.brand = brand
self.color = color
def describe(self):
print(f"Este auto es un {self.brand} de color {self.color}.")
class ElectricCar(Car):
def __init__(self, brand, color, battery_size):
super().__init__(brand, color)
self.battery_size = battery_size
def describe_battery(self):
print(f"La capacidad de la batería es de {self.battery_size} kWh.")
En este ejemplo, la clase ElectricCar
hereda las funcionalidades de la clase Car
y, además, añade la función de describir la capacidad de la batería. Se utiliza super()
para llamar al constructor de la clase padre e inicializar los atributos comunes (marca y color).
3. Sobrescritura de métodos
Sobrescritura es la capacidad de que una subclase vuelva a definir un método de su superclase. Con ello, es posible aprovechar los métodos de la superclase y, al mismo tiempo, modificar el comportamiento en la subclase.Ejemplo de sobrescritura
class Animal:
def speak(self):
print("Sonido de animal")
class Dog(Animal):
def speak(self):
print("¡Guau guau!")
En este ejemplo, la clase Dog
sobrescribe el método speak
de la clase Animal
. De este modo, en una instancia de la clase Dog
se imprime «guau guau», mientras que en una instancia de la clase Animal
se muestra «sonido de animal».4. Herencia múltiple
Herencia múltiple permite que una subclase herede de varias superclases. Con ello, es posible integrar las funcionalidades de diferentes clases en una sola clase, pero hay que tener cuidado, ya que la implementación puede volverse compleja.Ejemplo y consideraciones sobre la herencia múltiple
class A:
def greet(self):
print("Saludo de A")
class B:
def greet(self):
print("Saludo de B")
class C(A, B):
pass
c = C()
c.greet() # Se muestra "Saludo de A" (según el MRO, se prioriza la primera clase)
En Python, el MRO (Method Resolution Order) determina qué método de las superclases se invoca. Para comprobar este orden, utilice C.mro()
. La herencia múltiple es potente, pero debe usarse teniendo en cuenta los posibles conflictos entre superclases y el orden de los métodos.
5. Ejemplos prácticos con herencia
La herencia resulta útil en muchos escenarios incluso en la programación cotidiana. Por ejemplo, en un sistema de gestión de empleados de una empresa, heredar desde una clase básica de empleado para crear clases con cargos específicos permite la reutilización y la ampliación del código.Ejemplo práctico de un sistema de gestión de empleados
class Employee:
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
def fullname(self):
return f'{self.first} {self.last}'
class Manager(Employee):
def __init__(self, first, last, pay, employees=None):
super().__init__(first, last, pay)
self.employees = employees if employees is not None else []
def add_employee(self, employee):
if employee not in self.employees:
self.employees.append(employee)
def print_employees(self):
for emp in self.employees:
print(emp.fullname())
En este ejemplo, la clase Manager
hereda de la clase Employee
y añade funcionalidades de gestión de empleados. Al mantener las funcionalidades comunes de la clase base, se amplían las funciones según el cargo específico.6. Mejores prácticas de herencia y contraste con la composición
La herencia es muy poderosa, pero el uso excesivo puede complicar el código. En particular, la herencia múltiple puede volver complejas las relaciones entre clases, por lo que debe usarse con cautela. En estos casos, se recomienda utilizar composición en lugar de herencia.Ejemplo de composición
La composición es un patrón de diseño en el que una clase tiene otra clase como componente (instancia) y delega funcionalidad.class Engine:
def start(self):
print("El motor ha arrancado.")
class Car:
def __init__(self, engine):
self.engine = engine
def start(self):
self.engine.start()
engine = Engine()
car = Car(engine)
car.start() # Se mostrará "El motor ha arrancado."
Así, la composición es una forma de compartir funcionalidad entre clases sin usar herencia. Al incluir solo la funcionalidad necesaria, el código se vuelve más flexible y fácil de mantener.