Una guía para principiantes sobre la abstracción en la programación orientada a objetos

Cuando comes un burrito, cada uno de tus receptores gustativos canta con alegría. Cada bocado aporta una combinación de diferentes tipos de sabores, como salado, dulce, picante y umami. Cada bocado posterior tiene un sabor ligeramente diferente, ya que una nueva colección de ingredientes une sus sabores.

Es posible que haya leído los ingredientes del menú, pero no sabe exactamente cómo se prepara la salsa. El condimento que usan en sus verduras podría ser una mezcla secreta. Sin embargo, no es necesario conocer todos los ingredientes exactos. Basta saber que está delicioso.

Los ingredientes que conoces, como el arroz blanco, son concretos. Los otros elementos son abstractos. Sabes que es salsa, pero ¿de qué tipo? O, si alguien te da un burrito de la nada, entonces todo el burrito es abstracto.

Abstracción en lo abstracto

Junto con la herencia , la abstracción es un concepto importante en la programación orientada a objetos. La teoría es que cada objeto debe ofrecer resultados simples y predecibles. Los objetos también deben compartir solo lo que se necesita compartir.

La abstracción mantiene el código y los datos ocultos cuando es apropiado

Puedes pensar en un burrito como un objeto. Dentro del burrito, tienes varios otros objetos, como frijoles, arroz, queso y salsa picante. Es posible que los frijoles estén condimentados. El queso puede ser una mezcla. Y la salsa picante puede ser una combinación de pimientos añejados en vinagre.

No es necesario que sepas cómo se elaboraron todos los ingredientes de un burrito. Y en el caso de los perros calientes, probablemente no quieras saberlo. Lo único que importa es que no se deshaga al comerlo y que esté súper sabroso.

La abstracción está estrechamente ligada a la encapsulación

Es lo mismo con la programación de objetos. Cuando crea una instancia de un objeto (lo crea a partir de una clase), es como pedir un burrito en el mostrador de un camión de comida. Tiene acceso a algunos datos, pero no a todos. No necesita saber cómo funciona el objeto, siempre que las funciones devuelvan los datos correctos. Aquí hay un burrito en JavaScript / Typecript:

 class CheeseBlend {
private _ingredients = ["Colby Jack", "Cheddar", "Manchego"];
get ingredients() {
return "melted cheese";
}
}
class SecretSalsa {
private _ingredients = ["onions", "tomatoes", "cilantro", "Guatemalan Insanity Peppers"];
get ingredients() {
return "it's a secret";
}
}
class Burrito {
private _beans = "beans";
private _rice = "rice";
private _cheese: CheeseBlend = new CheeseBlend();
private _salsa: SecretSalsa = new SecretSalsa();
get cheese() {
return this._cheese.ingredients;
}
get salsa() {
return this._salsa.ingredients;
}
}
let burro = new Burrito();
console.log(burro.cheese);
console.log(burro.salsa);

Puedes jugar con este código en la zona de pruebas de TypeScript .

En el ejemplo anterior, se extraen los ingredientes de la salsa y el queso. Primero, están encapsulados para ocultar los ingredientes especiales. Luego se agregan getters para acceder a los ingredientes. Pero los ingredientes solo devuelven una representación abstracta de lo que realmente son.

Abstracción en el hormigón

Sin embargo, la abstracción es más que un concepto. Las clases también pueden ser abstractas. Eso significa que pueden definir otras clases. Pero no se pueden crear instancias de ellos mismos.

Por qué las clases a veces deberían ser abstractas

Imagina que vas a un restaurante y te sientas. El camarero te entrega un menú. Lo abres y descubres que solo hay un artículo: comida.

Eso es bastante abstracto. ¿Lo pedirías? ¿Te lo comerías? Probablemente no lo harías. Decir que algo es comida no es suficiente. Necesita descomponerse en algo más concreto.

¿Y la pasta? Bueno, ese es un tipo de comida más específico. Y sabemos que probablemente tenga fideos y salsa. Pero hay muchos tipos diferentes de pasta, por lo que sigue siendo abstracto.

¿Qué es abstracto y qué es concreto?

Fettuccine Alfredo es un ejemplo concreto de comida y pasta. Lo mismo se aplica a las clases. No se deben crear instancias de todas las clases. Algunas clases solo deberían definir la estructura de otras clases.

Aquí hay un ejemplo con una clase de comida abstracta y una clase de MacadamiaNuts infantil:

 abstract class Food {
constructor(public name: String) {}
abstract totalCalories(): number;
abstract description(): string;
abstract flavor(): string;
}
class MacadamiaNuts extends Food {
constructor() {
super("One Cup of Macadamia Nuts");
}
totalCalories() {
return 962;
}
description() {
return "A nut from Hawaii.";
}
flavor() {
return "rich, buttery, and nutty";
}
}
let nuts = new MacadamiaNuts();
console.log(nuts.name)
console.log(nuts.description())

Aquí está el código.

Las clases abstractas le dicen a otras clases cómo se supone que deben comportarse. En el ejemplo anterior, si va a ser una clase de comida, debe tener funciones que le permitan acceder a su nombre, sabor, descripción y calorías.

Observe que la clase MacadamiaNuts amplía Food . Es decir que MacadamiaNuts se compromete a seguir las reglas de Alimentos . Además, observe que el constructor llama a super . Ese comando crea una instancia de la clase principal antes de que el constructor cree una instancia de MacadamiaNuts .

Si está aprendiendo a programar, puede divertirse más con estos juegos de programación .

Práctica de abstracción

  • Visite el enlace de arriba y use la caja de arena para crear una clase abstracta llamada Sopa.
  • Cree un niño concreto de la clase Sopa , llamado Cereal .
  • Usa console.log para probar tu código. ¿Qué sucede si a su clase Cereal le falta una de las funciones definidas en Soup ?

Pero, ¿cuál es el sentido de una clase que no puede instanciar?

Al principio, las clases abstractas pueden parecer innecesarias. Después de todo, en realidad no puedes usarlos para hacer un objeto. Y no es como si transmitieran sus funciones. Las funciones deben reescribirse en cada clase infantil.

Hay dos razones principales por las que necesita clases abstractas. Mantienen su código coherente y se aseguran de que otros desarrolladores también escriban código coherente. No siempre trabajarás solo. Todo el equipo debe seguir las mismas reglas. Puede obtener más información en la documentación de TypeScript sobre clases abstractas .