Clases Abstractas
Introducción
Palabra reservada: abstract
En Java, una clase abstracta es una clase que no se puede instanciar directamente, lo que significa que no puedes crear objetos directos de una clase abstracta. En su lugar, se utilizan como clases base para otras clases derivadas, a menudo llamadas subclases o hijas. Las clases abstractas son una parte fundamental de la programación orientada a objetos en Java y se utilizan para definir una estructura común y compartir comportamientos entre clases relacionadas.
Definición
Para declarar una clase como abstracta, debes usar la palabra clave abstract en la definición de la clase. Por ejemplo:
abstract class Figura {
// ...
}
Una vez que creamos una clase abstracta, mediante herencia la podemos usar a modo “plantilla” para las subclases:
class Circulo extends Figura {
private double radio;
public Circulo(double radio) {
this.radio = radio;
}
@Override
double calcularArea() {
return Math.PI * radio * radio;
}
}
Métodos abstractos
Una clase abstracta puede contener métodos abstractos. Un método abstracto es un método que se declara en la clase abstracta pero no se implementa en la misma. Los métodos abstractos deben ser implementados en las subclases. Y ójo -> si creamos un método abstracto la clase también tiene que ser. Pero una clase abstracta no implica que todos sus métodos sean abstractos.
Ejemplo
Suponemos que no existen los “empleados genéricos”, solo pueden ser Fijos, temporales y comerciales, por tanto, no tiene sentido calcular la nómina de un empleado genérico. Pero obligamos a todas las subclases a que lo implementen:
class Empleado{
String nombre;
int ant;
int sueldoBase=1000;
public Empleado(String nombre, int ant) {
this.nombre = nombre;
this.ant = ant;
}
}
class EmpleadoFijo extends Empleado{
public EmpleadoFijo(String nombre, int ant) {
super(nombre, ant);
}
int calcularNomina() {
return sueldoBase+100*ant;
}
}
class EmpleadoTemporal extends Empleado{
public EmpleadoTemporal(String nombre, int ant) {
super(nombre, ant);
}
int calcularNomina() {
return sueldoBase+50*ant;
}
}
class EmpleadoComercial extends Empleado{
int comision;
public EmpleadoComercial(int comision, String nombre, int ant) {
super(nombre, ant);
this.comision = comision;
}
int calcularNomina() {
return sueldoBase+comision;
}
}
public class Unidad4 {
public static void main(String[] args) {
EmpleadoFijo eFijo=new EmpleadoFijo("fijo",10);
System.out.println("Nomina de "+ eFijo.nombre+": "+eFijo.calcularNomina());
EmpleadoTemporal eTemporal=new EmpleadoTemporal("temporal",5);
System.out.println("Nomina de "+ eTemporal.nombre+": "+eTemporal.calcularNomina());
EmpleadoComercial eComercial=new EmpleadoComercial(30,"comercial",5);
System.out.println("Nomina de "+ eComercial.nombre+": "+eComercial.calcularNomina());
}
}
Motivo
Las clases abstractas son útiles cuando deseas definir una estructura común para un grupo de clases relacionadas o cuando deseas asegurarte de que ciertos métodos se implementen en las subclases. No puedes crear objetos directos de una clase abstracta, pero puedes crear instancias de las subclases. Es un elemento clave para el polimorfismo (un pilar de la O.O.) que veramos más adelante.
Otra justificación de una clase sin objetos es esta:
- A veces queremos que el padre (superclase) garantice que todos sus hijos se vean obligados a implementar los métodos del padre -> herencia obligatoria.
- Que un diseñador de la jerarquía (un analista o un jefe de programadores por ejemplo) imponga reglas a los programadores que la desarrollan.
- Si es una clase muy genérica y padre y no queremos que se crean objetos de ella, se configura abstracta.
Ejercicio 1
Escribe un ejemplo cualquiera, lo más simple posible, en el que se aprecie que una clase abstracta, aunque no tenga sentido, no tiene porqué contener un método abstracto. Es decir, no hay error de compilación al escribir una clase abstracta sin método abstracto.
Ejercicio 2
De la misma forma, demuestra ahora que si una clase contiene un método abstracto, dicha clase debe declararse abstracta, en caso contrario, obtenemos error de compilación.
Ejercicio 3
De la misma forma, demuestra ahora que una clase abstracta no es instanciable.
Ejercicio 4
¿Que falta en el siguiente código?
abstract class Item {
protected String titulo;
protected float precio = 5.0f;
public abstract boolean esAlquilable();
public float getPrecio() {
return precio;
}
}
class Pelicula extends Item {
public boolean esAlquilable() {
return true;
}
}
class Libro extends Item {
public float getPrecio() {
return 0.0f;
}
}
class TestAbstract {
public static void main (String[] args) {
Pelicula pelicula = new Pelicula();
Libro libro = new Libro();
System.out.println(pelicula.esAlquilable());
System.out.println(libro.getPrecio());
}
}
Ejercicio 5
Escribe código para implantar la siguiente estructura. Luego en main de Unidad4 crea un triángulo y un círculo y calcula su área.
Sabemos que una clase/método es abstracta por que su nombre está en cursiva.
Las flechas indican una relación de herencia “un triángulo es una Figura” y un “Círculo es una figura”.