Cuando aprendemos programación orientada a objetos, solemos encontrarnos con una lista conocida:
- Encapsulamiento
- Abstracción
- Herencia
- Polimorfismo
Los famosos cuatro pilares de la orientación a objetos.
Pero hay una pregunta previa que pocas veces nos hacemos: ¿Qué significa realmente que un lenguaje sea orientado a objetos?
Porque tener clases, métodos o herencia no necesariamente alcanza para responderla.
Una primera aproximación podría ser: un lenguaje orientado a objetos es aquel que permite definir clases y crear objetos.
El problema es que esta definición es demasiado débil.
Si fuera suficiente con tener clases, entonces cualquier lenguaje que incorpore una construcción class sería automáticamente orientado a objetos.
Y sabemos que no es tan sencillo.
En realidad, una clase es solamente una forma de representar una abstracción.
Podemos partir de un conjunto de objetos concretos:
Dog
Cat
Horse
y abstraer aquello que tienen en común:
Animal
/ | \
Dog Cat Horse
La abstracción nos permite pasar de casos particulares a una representación general.
Y podemos volver a abstraer:
Dog
Cat
Horse
↓
Animal
↓
LivingBeing
Por eso, si entendemos la abstracción como un proceso de generalización, la clasificación de objetos y la construcción de jerarquías son manifestaciones de una misma actividad conceptual.
La clase no es la orientación a objetos.
Es una herramienta para representar determinadas abstracciones.
Entonces, ¿qué papel juegan los objetos?
Acá aparece una idea mucho más interesante.
La orientación a objetos no consiste simplemente en dividir un programa en estructuras llamadas clases.
Consiste en modelar el sistema alrededor de objetos que encapsulan estado y comportamiento y que colaboran entre sí.
Un objeto no es solamente un conjunto de datos.
Tiene:
- identidad;
- estado;
- comportamiento.
Y, fundamentalmente, puede interactuar con otros objetos.
En la visión clásica de Smalltalk, esta interacción se expresa mediante mensajes.
Esto es importante porque cambia nuestra perspectiva: El centro de la orientación a objetos no es necesariamente la clase. Es el objeto y la colaboración entre objetos.
Las clases son una de las formas que tenemos de definir cómo se construyen esos objetos.
¿Y el polimorfismo? El polimorfismo aparece cuando podemos trabajar con diferentes objetos a través de una abstracción común.
Por ejemplo:
class Animal {
public:
virtual void speak() = 0;
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
void speak() override {
std::cout << "Woof\n";
}
};
class Cat : public Animal {
public:
void speak() override {
std::cout << "Meow\n";
}
};
Podemos tener:
std::vector<std::unique_ptr<Animal>> animals;
animals.push_back(std::make_unique<Dog>());
animals.push_back(std::make_unique<Cat>());
for (auto& animal : animals) {
animal->speak();
}
El código que utiliza Animal no necesita conocer la implementación concreta.
La abstracción establece el comportamiento que nos interesa:
Animal
└── speak()
y el polimorfismo permite que diferentes objetos proporcionen diferentes implementaciones de ese comportamiento.
Por lo tanto:La abstracción define una perspectiva común; el polimorfismo permite trabajar con diferentes realizaciones de esa perspectiva.
¿Y C++? C++ es un caso particularmente interesante.
C++ tiene:
- clases;
- encapsulamiento;
- herencia;
- polimorfismo;
- métodos virtuales;
- objetos.
Entonces es perfectamente posible escribir programas con un diseño fuertemente orientado a objetos.
Pero C++ no es exclusivamente orientado a objetos.
También podemos escribir:
int sum(int a, int b) {
return a + b;
}
usar templates:
template<typename T>
T max(T a, T b) {
return a > b ? a : b;
}
usar funciones libres, algoritmos genéricos, programación procedural, metaprogramación, RAII, etc.
Por eso suele ser más preciso decir que C++ es un lenguaje multiparadigma que soporta programación orientada a objetos.
Y esta distinción es importante.
¿Entonces C++ es o no es orientado a objetos? La respuesta depende de qué estemos preguntando.
Si preguntamos: ¿C++ permite programación orientada a objetos?
La respuesta es claramente sí.
Si preguntamos: ¿Todo programa C++ es un programa orientado a objetos?
La respuesta es no.
Y si preguntamos: ¿C++ define qué significa orientación a objetos?
La respuesta también es no.
C++ implementa una determinada interpretación de la orientación a objetos.
Y esto nos lleva a una distinción que considero fundamental:Un paradigma no es una lista de características que un lenguaje debe implementar. Es una determinada forma de modelar y resolver problemas.
¿Y los cuatro pilares?
Desde esta perspectiva, los cuatro pilares tradicionales empiezan a verse de otra manera.
Encapsulamiento es una estrategia para mantener estado y comportamiento bajo el control del objeto.
Abstracción es un proceso conceptual mediante el cual identificamos lo esencial y generalizamos.
Herencia es un mecanismo para expresar relaciones de especialización/generalización.
Polimorfismo permite trabajar con diferentes implementaciones a través de una abstracción común.
Pero no están necesariamente en el mismo nivel conceptual.
La abstracción es una actividad de modelado.
La herencia es un mecanismo del lenguaje.
El polimorfismo es una propiedad que permite sustituir diferentes implementaciones.
Y el encapsulamiento es una estrategia para organizar el estado y comportamiento.
Por eso, quizás deberíamos dejar de pensar en los cuatro como cuatro piezas independientes que, juntas, mágicamente producen OOP. Entonces, ¿qué hace que algo sea orientado a objetos?
No existe una frontera universalmente aceptada.
Pero podemos pensar en una serie de ideas centrales:
ORIENTACIÓN A OBJETOS
Objetos
│
┌─────────┴─────────┐
│ │
Estado propio Comportamiento
│ │
└─────────┬─────────┘
│
Encapsulamiento
│
Colaboración
│
Mensajes
│
Polimorfismo
│
Abstracciones
Las clases, la herencia, las interfaces, los traits o los métodos son mecanismos concretos que distintos lenguajes utilizan para expresar estas ideas.
Por eso podemos encontrar lenguajes con clases que no ponen realmente a los objetos en el centro, y lenguajes que permiten muchos de los principios de OOP sin tener clases ni herencia tradicional.
Y ahí aparece una pregunta todavía más interesante: Si podemos tener encapsulamiento, abstracción y polimorfismo sin herencia de clases, ¿la herencia es realmente un pilar de la orientación a objetos?
Esa es precisamente la pregunta que vale la pena explorar después.







.jpeg)




