Dominando la Abstracción de Datos en C++: Simplifica el Diseño con Separación Interfaz-Implementación
La abstracción de datos se refiere a proporcionar solo información esencial al mundo exterior y ocultar sus detalles de fondo, es decir, representar la información necesaria en el programa sin presentar los detalles.
La abstracción de datos es una técnica de programación (y diseño) que se basa en la separación de interfaz e implementación.
Tomemos un ejemplo de la vida real de un televisor, el cual puedes encender y apagar, cambiar el canal, ajustar el volumen, y agregar componentes externos como parlantes, VCRs y reproductores de DVD, PERO no conoces sus detalles internos, es decir, no sabes cómo recibe señales por el aire o por cable, cómo las traduce y finalmente las muestra en la pantalla.
Así, podemos decir que un televisor separa claramente su implementación interna de su interfaz externa y puedes jugar con sus interfaces como el botón de encendido, cambiador de canales y control de volumen sin tener ningún conocimiento de sus internos.
En C++, las clases proporcionan un gran nivel de abstracción de datos. Proporcionan métodos públicos suficientes al mundo exterior para jugar con la funcionalidad del objeto y manipular los datos del objeto, es decir, el estado sin realmente saber cómo la clase ha sido implementada internamente.
Por ejemplo, tu programa puede hacer una llamada a la función sort() sin saber qué algoritmo usa la función realmente para ordenar los valores dados. De hecho, la implementación subyacente de la funcionalidad de ordenamiento podría cambiar entre versiones de la biblioteca, y mientras la interfaz se mantenga igual, tu llamada a la función seguirá funcionando.
En C++, usamos clases para definir nuestros propios tipos de datos abstractos (ADT). Puedes usar el objeto cout de la clase ostream para enviar datos a la salida estándar como esto:
#include <iostream>
using namespace std;
int main() {
cout << "Hola C++" << endl;
return 0;
}
Aquí, no necesitas entender cómo cout muestra el texto en la pantalla del usuario. Solo necesitas conocer la interfaz pública y la implementación subyacente de 'cout' es libre de cambiar.
Etiquetas de Acceso Refuerzan la Abstracción
En C++, usamos etiquetas de acceso para definir la interfaz abstracta a la clase. Una clase puede contener cero o más etiquetas de acceso:
Los miembros definidos con una etiqueta public son accesibles a todas las partes del programa. La vista de abstracción de datos de un tipo es definida por sus miembros públicos.
Los miembros definidos con una etiqueta private no son accesibles al código que usa la clase. Las secciones privadas ocultan la implementación del código que usa el tipo.
No hay restricciones en cuántas veces puede aparecer una etiqueta de acceso. Cada etiqueta de acceso especifica el nivel de acceso de las definiciones de miembros sucesivas. El nivel de acceso especificado permanece en efecto hasta que se encuentra la siguiente etiqueta de acceso o se ve la llave de cierre derecha del cuerpo de la clase.
Beneficios de la Abstracción de Datos
La abstracción de datos proporciona dos ventajas importantes:
Los internos de la clase están protegidos de errores inadvertidos a nivel de usuario, que podrían corromper el estado del objeto.
La implementación de la clase puede evolucionar con el tiempo en respuesta a requisitos cambiantes o reportes de errores sin requerir cambios en el código a nivel de usuario.
Al definir miembros de datos solo en la sección privada de la clase, el autor de la clase es libre de hacer cambios en los datos. Si la implementación cambia, solo el código de la clase necesita ser examinado para ver qué efecto puede tener el cambio. Si los datos son públicos, entonces cualquier función que acceda directamente a los miembros de datos de la vieja representación podría romperse.
Ejemplo de Abstracción de Datos
Cualquier programa C++ donde implementes una clase con miembros públicos y privados es un ejemplo de abstracción de datos. Considera el siguiente ejemplo:
#include <iostream>
using namespace std;
class Sumador {
public:
// constructor
Sumador(int i = 0) {
total = i;
}
// interfaz al mundo exterior
void agregarNum(int numero) {
total += numero;
}
// interfaz al mundo exterior
int obtenerTotal() {
return total;
};
private:
// datos ocultados del mundo exterior
int total;
};
int main() {
Sumador a;
a.agregarNum(10);
a.agregarNum(20);
a.agregarNum(30);
cout << "Total " << a.obtenerTotal() << endl;
return 0;
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Total 60
La clase anterior suma números y retorna la suma. Los miembros públicos - agregarNum y obtenerTotal son las interfaces al mundo exterior y un usuario necesita conocerlos para usar la clase. El miembro privado total es algo que el usuario no necesita saber, pero es necesario para que la clase opere correctamente.
Estrategia de Diseño
La abstracción separa el código en interfaz e implementación. Así que al diseñar tu componente, debes mantener la interfaz independiente de la implementación para que si cambias la implementación subyacente, la interfaz permanezca intacta.
En este caso, cualquier programa que use estas interfaces no se verá impactado y solo necesitará una recompilación con la última implementación.
Lenguaje C
- Entendiendo los Tipos de Datos en C++: Fundamentos, Modificadores y Mejores Prácticas
- Dominando los Operadores en C++: Guía Completa con Ejemplos Prácticos
- Clases y Objetos en C++: Guía Práctica de Programación Orientada a Objetos
- Dominando las plantillas de clase en C++: guía práctica
- Dominando el tipo de dato char en C++: Declaración, ASCII y técnicas de conversión
- Entendiendo las Clases de Almacenamiento en C++: Alcance, Vida y Uso
- Estructuras de Datos en C++: Construyendo Programas Eficientes con Arrays, Structs y Más
- Entendiendo el Polimorfismo en C++: Guía Práctica
- Encapsulamiento de Datos en C++: Protege tu Código
- Abstracción en Java Explicada: Simplifica Código y Mejora Legibilidad
- Estructuras de Datos en Java: Explorando Clases Core y Collections Framework