Conceptos de la Programación Orientada a Objetos (POO)
La Programación Orientada a Objetos es un paradigma que estructura el software en torno a "objetos" en lugar de funciones o lógica pura. Mientras que la programación procedimental se enfoca en una secuencia lógica de pasos para resolver un problema (como una receta), la POO busca modelar entidades del mundo real.
Al abstraer conceptos complejos en clases y objetos, logramos sistemas más fáciles de mantener, escalar y reutilizar. Este enfoque alinea el diseño del código con la forma en que los humanos percibimos el mundo.
Definición de Clases
Una clase es un plano o plantilla que define las características y comportamientos de un grupo de objetos similares. En Python, la snitaxis básica es:
class NombreDeLaClase:
# Cuerpo de la clase
pass
Consideraciones clave:
- Palabra reservada
class: Se utiliza para iniciar la definición. - Convención CamelCase: Los nombres de las clases suelen escribirse con la primera letra de cada palabra en mayúscula.
- El parámetro
self: Representa la instancia específica del objeto que se está manipulando. Es el primer parámetro obligatorio en los métodos de instancia. - Constructor
__init__: Es un método especial que se ejecuta automáticamente al crear un objeto, permitiendo inicializar sus atributos.
Instanciación de Objetos
La instanciación es el proceso de crear un objeto concreto a partir de una clase. Se realiza llamando a la clase como si fuera una función.
class Robot:
def __init__(self, modelo, version):
self.modelo = modelo
self.version = version
# Creación de una instancia
mi_robot = Robot("RX-78", 2.0)
# Verificación de tipo
print(isinstance(mi_robot, Robot)) # Devuelve True
Durante este proceso, los argumentos pasados a la clase se dirigen al método __init__, configurando el estado inicial del objeto.
Atributos de Clase y de Instancia
Existen dos niveles donde podemos almacenar datos dentro de la POO en Python:
- Atributos de Clase: Son variables compartidas por todas las instancias de la clase. Si se modifica un atributo de clase (siendo este un objeto mutable como una lista), el cambio se refleja en todos los objetos.
- Atributos de Instancia: Son variables únicas para cada objeto, definidas usualmente dentro del constructor mediante
self.nombre_variable.
class Sensor:
tipo_senal = "Digital" # Atributo de clase
def __init__(self, id_sensor):
self.id_sensor = id_sensor # Atributo de instancia
Privacidad y Encapsulamiento
El encapsulamiento protege la integridad de los datos ocultando los detalles internos de implementación. Python utiliza convenciones de nomenclatura para indicar el nivel de acceso:
- Un guion bajo (
_variable): Indica que el atributo es para uso interno (protegido). Es una convención para desarrolladores. - Doble guion bajo (
__variable): Activa el "Name Mangling", dificultando el acceso accidental desde fuera de la clase (privado). - Doble guion bajo inicial y final (
__init__): Identifica métodos especiales o "dunder methods" del lenguaje.
Herencia
La herencia permite que una clase (hija o derivada) adopte los atributos y métodos de otra clase (padre o base). Esto facilita enormemente la reutilización de código.
class Vehiculo:
def mover(self):
print("El vehículo se está desplazando")
class Drone(Vehiculo):
def volar(self):
print("El drone está volando")
# El drone hereda 'mover' de Vehiculo
mi_drone = Drone()
mi_drone.mover()
Si una clase hija redefine un método presente en la clase padre, se produce una sobreescritura. Para llamar al método original del padre desde el hijo, se uttiliza la función super().
Polimorfismo
El polimorfismo es la capacidad de diferentes clases para responder al mismo mensaje o nombre de método de formas distintas. En términos prácticos, permite tratar a objetos de diferentes tipos de manera uniforme si comparten la misma interfaz.
class Perro:
def hablar(self):
return "Guau!"
class Gato:
def hablar(self):
return "Miau!"
def hacer_ruido(animal):
print(animal.hablar())
hacer_ruido(Perro()) # Salida: Guau!
hacer_ruido(Gato()) # Salida: Miau!
Aquí, la función hacer_ruido no necesita saber qué tipo de animal recibe, siempre que el objeto tenga el método hablar() implementado.