La abstracción en Java ayuda a minimizar la complejidad. Consiste en ocultar detalles innecesarios y exponer solo las funcionalidades destinadas a la interacción con el usuario. En otras palabras, la abstracción de datos es el proceso de reducir los objetos de Java a su esencia para que solo revelen las características necesarias para los usuarios.
Por ejemplo, al enviar un correo electrónico, solo necesita ingresar la dirección de correo electrónico, el asunto y el texto del destinatario. Del lado del usuario, la aplicación revela lo que necesita para hacer el trabajo. Sin embargo, otras implementaciones aparecen en segundo plano, como la conexión al servidor, el formateo de correo electrónico y el cifrado, entre otras. Estos procesos se ocultan al usuario mediante abstracción.
Este artículo define la abstracción en el contexto de Java, cómo funciona la abstracción en Java y funciona a través de un ejemplo del uso de la abstracción.
¿Cómo funciona la abstracción?
Antes de examinar la abstracción en Java, analicemos cómo funciona la abstracción de datos. En Java, puede tener clases abstractas y métodos abstractos.
Clases abstractas
Dado que Java es un lenguaje de programación orientado a objetos (POO), la abstracción es esencial en Java. OOP se enfoca en crear objetos que contienen datos y métodos. Cada objeto pertenece a una clase, lo que significa que cada objeto en Java pertenece a una clase.
Por ejemplo, puede trabajar con una clase llamada fruta y un plátano puede ser un objeto de esa clase. En Java, los objetos se definen por su comportamiento (métodos), interfaces (cómo se comunican con otros objetos) y propiedades (atributos).
Una clase abstracta se identifica mediante el uso de la palabra clave abstracta en la definición de la clase, como se muestra en el siguiente fragmento de código:
abstract class Name {
/*the body of the class*/
}
En Java, las clases abstractas permiten una abstracción parcial o completa. La abstracción parcial se logra mediante implementaciones con métodos específicos. La abstracción total se logra a través de interfaces con tipos abstractos que determinan el comportamiento de la clase.
Aquí hay algunas reglas importantes a tener en cuenta cuando se trabaja con clases abstractas:
- Pueden contener métodos abstractos (métodos sin cuerpo).
- Una clase con un método abstracto debe declararse como una clase abstracta.
- Una clase declarada abstract no puede ser instanciada.
- Una clase no puede contener métodos estáticos o terminales en su cuerpo.
- Una clase que hereda una clase abstracta también debe implementar todos sus métodos abstractos.
método abstracto
Los métodos abstractos son métodos sin contenido y sin implementación real. Se utilizan cuando desea agregar un método a una clase y dejar la determinación de su implementación a las clases secundarias.
Declaras un método abstracto usando la palabra clave abstract. Sigue la firma del método pero no tiene contenido. En lugar de agregar las llaves al final, agregue un punto y coma:
/*abstract class*/
public abstract class ParentClass{
/*abstract method*/
public abstract double MethodA();
}
Solo las clases abstractas pueden contener métodos abstractos. Una clase que hereda una clase abstracta debe implementar todos sus métodos abstractos. Por ejemplo, si una clase heredó la clase abstracta del ejemplo anterior, se vería así:
/*inheriting the abstract class*/
public class ChildClass extends ParentClass {
/*implementing the abstract method from the abstract class*/
public double MethodA() {
}
}
Abstracción de datos y abstracción de control
Hay dos tipos de abstracción en Java: abstracción de datos y abstracción de control.
La abstracción de datos le permite crear tipos de datos complejos como HashMap o HashSet y ocultar cómo se implementan a los usuarios. Obtendrá mejores resultados con HashMaps y HashSets si sabe cómo estructurar sus datos con ellos.
La abstracción de control es el proceso de consolidación de todas las instrucciones similares y repetitivas en un todo. Esta abstracción se utiliza para crear una función para realizar una tarea específica.
Abstracción y encapsulación de datos
La encapsulación de datos es un mecanismo de Java para asociar datos/variables con un método que opera sobre esos datos. Consiste en restringir el acceso a la información dentro de una clase fuera de esta clase. En Java, los datos encapsulados se etiquetan con el término privado en la definición de clase y se accede a ellos a través del método get o set.
La encapsulación de datos y la abstracción de datos son los conceptos básicos de OOP. Son similares en el sentido de que ocultan componentes esenciales de otros usuarios de código para mejorar la seguridad. Ambos permiten un acceso limitado a sus componentes sin revelar detalles esenciales.
La diferencia entre ellos es que la encapsulación de datos se enfoca en ocultar los datos, mientras que la abstracción de datos se enfoca en ocultar el proceso de implementación.
¿Por qué utilizar la abstracción de datos?
En el desarrollo de aplicaciones, la abstracción ofrece varias ventajas:
- Simplifica eficazmente los procesos complejos con los que interactúa el usuario.
- La combinación suelta que promueve la abstracción reduce la sobrecarga de depuración porque la implementación y las funciones están separadas.
- La abstracción ayuda a crear código eficiente al permitir la reutilización del código.
- La abstracción aumenta la seguridad al ocultar los detalles básicos de implementación.
Un ejemplo de abstracción en Java
Para ver cómo funciona la abstracción, eche un vistazo al siguiente ejemplo. Suponga que trabaja para una empresa de alquiler de coches y desea enviar una factura a los clientes. También desea que la aplicación calcule el monto total que debe el cliente.
Para preparar esta factura, comienza creando una clase abstracta:
public abstract class Car {
private String name;
private String regNumber;
private int number;
public Car(String regNumber, String name) {
this.name = name;
this.regNumber = regNumber;
}
public void mailInvoice() {
System.out.println("Mailing an invoice for: " + this.name + " Registration: " + this.regNumber);
}
public String toString() {
return name + " " + regNumber;
}
public String getName() {
return name;
}
public String getRegNumber() {
return regNumber;
}
/*Creating an abstract method to be implemented by child classes*/
public abstract void computeCost();
}
Entonces necesitas heredar la clase abstracta. Para ello, cree una clase específica y agregue una extensión de término después del nombre de la clase seguida de una clase abstracta heredada:
public class RentalCost extends Car {
/* cost of the vehicle per hour*/
private double costPerHour;
private double hours; /* number of hours spent with the vehicle*/
private double cost;/* Total amount due*/
public RentalCost(String regNumber, String name, double costPerHour, double hours) {
super(regNumber, name);
setCost(costPerHour, hours);
}
public void mailInvoice() {
System.out.println("Mailing invoice for " + getName() + " with amount due as " + cost);
}
public double getCostPerHour() {
return costPerHour;
}
public double getHours() {
return hours;
}
public void setCost(double newCost, double newHours) {
if(newCost >= 0.0 && newHours>=0.0) {
costPerHour = newCost;
hours = newHours;
cost = costPerHour * hours;
}
}
/*Implementing the abstract method from the inherited abstract Car class*/
public void computeCost() {
System.out.println("Total cost for:" + getName() + " is " + cost);
}
}
Tenga en cuenta que no puede instanciar la clase Car. Sin embargo, puede crear instancias de la clase Cost y acceder a todos los métodos dentro de la clase Car como se muestra en el código a continuación:
public class Invoice {
public static void main(String [] args) {
RentalCost a = new RentalCost("11DA", "Honda CRV", 50.00, 4.5);
System.out.println("mailInvoice() called using Cost as reference");
a.mailInvoice();
System.out.println("nnCalling method computeCost() from abstract 'Car class' that's implemented in concrete 'Cost class'");
a.computeCost();
}
}
El resultado que obtiene cuando ejecuta esta aplicación es el siguiente:
mailInvoice() called using Cost as reference
Mailing invoice for Honda CRV with amount due as 225.0
Calling method computeCost() from abstract 'Car class' that's implemented in concrete 'Cost class'
Total cost for:Honda CRV is 225.0
Ejemplo de abstracción: clase abstracta frente a interfaz
La abstracción en Java se logra utilizando una clase o interfaz abstracta.
La interfaz en Java representa un plan de clase e incluye métodos abstractos y constantes estáticas. Las interfaces son similares a las clases abstractas en que no se pueden crear y no pueden admitir uno o más métodos declarados sin ninguna implementación.
A diferencia de una interfaz que solo puede especificar métodos, una clase debe implementar una clase abstracta que puede contener datos y métodos específicos. Además, al usar la interfaz, puede limitar la cantidad de métodos abstractos declarados. Esto no es posible con una clase abstracta.
Este ejemplo usa una clase abstracta porque las necesidades de abstracción se pueden cumplir con una sola herencia. Además, este ejemplo usa la abstracción de clases para ocultar cómo se calculan los costos y cómo se procesan las facturas. Por tanto, el usuario sólo tiene acceso a lo necesario para generar la factura.
Primeros pasos con la abstracción de Java
La abstracción en Java es muy efectiva para limitar lo que comparte con los usuarios, y puede elegir el nivel de abstracción que desea implementar en su aplicación. Puede usar métodos específicos en clases abstractas para una abstracción parcial e interfaces para una abstracción completa.
Los métodos abstractos son necesarios cuando deja la tarea de determinar la implementación a la clase descendiente.
Como lenguaje de programación orientada a objetos, Java utiliza la abstracción de datos. Además de proporcionar a los usuarios solo la información que necesitan, ayuda a reducir la complejidad y el esfuerzo necesarios para el desarrollo de aplicaciones.








