5: Programación Orientada a Objetos (POO)
5.1 ¿Qué es la Programación Orientada a Objetos?
La Programación Orientada a Objetos (POO) es un paradigma de programación que organiza el código alrededor de objetos en lugar de funciones y lógica. En la POO, todo se modela como un objeto, que representa una entidad del mundo real. Piensa en objetos como un Coche
, un Perro
o un Usuario
.
Cada objeto tiene dos características principales:
- Atributos: Las propiedades o características del objeto. (Ej. para un
Coche
:color
,marca
,velocidad
). - Métodos: Las acciones que el objeto puede realizar. (Ej. para un
Coche
:acelerar()
,frenar()
,arrancar()
).
La POO se basa en cuatro pilares:
- Herencia: Permite que una clase (hija) herede atributos y métodos de otra clase (padre).
- Polimorfismo: Permite que un mismo método se comporte de manera diferente en distintas clases.
- Encapsulamiento: Agrupa los datos y los métodos que los manipulan dentro de una misma unidad (la clase), y los protege de ser modificados externamente.
- Abstracción: Muestra solo los detalles relevantes del objeto al usuario, ocultando la complejidad interna.
5.2 Clases y Objetos
Una clase es como un "plano" o una plantilla para crear objetos. Es la definición de los atributos y métodos que tendrán los objetos que se creen a partir de ella. Un objeto es una instancia de una clase.
Definiendo una clase
Para definir una clase, usamos la palabra clave class
. Los nombres de las clases suelen escribirse con la primera letra en mayúscula (CamelCase
).
class Coche:
# El método __init__ es el constructor
def __init__(self, marca, color):
self.marca = marca
self.color = color
# Un método de la clase
def acelerar(self):
print(f"El coche {self.marca} está acelerando.")
El método __init__
es especial; se le conoce como el constructor. Se ejecuta automáticamente cuando creas un nuevo objeto. El primer parámetro, self
, es una referencia al objeto que se está creando. Los atributos definidos con self.
(ej. self.marca
) pertenecen al objeto.
Creando objetos (instancias)
Para crear un objeto a partir de la clase, simplemente llamas al nombre de la clase como si fuera una función.
# Crear dos objetos de la clase Coche
coche1 = Coche("Ford", "rojo")
coche2 = Coche("Tesla", "negro")
# Acceder a los atributos del objeto
print(coche1.color) # Salida: rojo
# Llamar a un método del objeto
coche2.acelerar() # Salida: El coche Tesla está acelerando.
5.3 Herencia y Polimorfismo
Herencia
La herencia nos permite crear una nueva clase (clase hija) que reutiliza los atributos y métodos de una clase existente (clase padre). Esto es útil para modelar relaciones del tipo "es un". Por ejemplo, un CocheElectrico
es un tipo de Coche
.
# Clase padre
class Vehiculo:
def __init__(self, marca):
self.marca = marca
def describir(self):
print(f"Este es un vehículo de la marca {self.marca}.")
# Clase hija que hereda de Vehiculo
class Coche(Vehiculo):
def __init__(self, marca, color):
# Llamar al constructor de la clase padre
super().__init__(marca)
self.color = color
def describir(self):
print(f"Este es un coche de la marca {self.marca} y color {self.color}.")
coche_tesla = Coche("Tesla", "gris")
coche_tesla.describir() # Salida: Este es un coche de la marca Tesla y color gris.
La función super()
se usa para llamar a un método de la clase padre, en este caso, su constructor.
Polimorfismo
El polimorfismo significa que objetos de diferentes clases pueden responder a la misma llamada de método de manera distinta. En el ejemplo anterior, la clase hija Coche
sobrescribe el método describir()
de la clase padre Vehiculo
para adaptarlo a su propia funcionalidad.
# Crear objetos de diferentes clases
vehiculo_generico = Vehiculo("Generico")
coche_tesla = Coche("Tesla", "gris")
vehiculo_generico.describir() # Salida: Este es un vehículo de la marca Generico.
coche_tesla.describir() # Salida: Este es un coche de la marca Tesla y color gris.
Ambos objetos tienen un método describir()
, pero el comportamiento es diferente para cada uno. ¡Esto es polimorfismo en acción!
La POO te proporciona un conjunto de herramientas poderosas para construir aplicaciones robustas y bien organizadas. En el siguiente módulo, exploraremos cómo organizar tu código en archivos y paquetes para proyectos más grandes.