Clases Abstractas (Abstract) en Java

Clases

Algunas veces querrá crear una superclase que defina solo una forma generalizada que será compartida por todas sus subclases, dejando que cada subclase complete los detalles. Dicha clase determina la naturaleza de los métodos que las subclases deben implementar, pero no proporciona una implementación de uno o más de estos métodos.

Requisitos para Leer
Anulación de Métodos

1. Clase abstracta

Una forma en que puede ocurrir esta situación es cuando una superclase no puede crear una implementación significativa para un método. Este es el caso con la versión de DosDimensiones utilizada en el siguiente ejemplo.

class DosDimensiones{
     private double base;
     private double altura;
     private String nombre;

     //Constructor por defecto
    DosDimensiones(){
        base=altura=0.0;
        nombre="ninguno";
    }

    //Parametrizando constructor
    DosDimensiones(double b, double h, String n){
        base= b;
        altura= h;
        nombre=n;
    }

    //Construir objeto con misma base y altura
    DosDimensiones(double x, String n){
        base=altura=x;
        nombre=n;
    }

    //Construir un objeto desde un objeto
    DosDimensiones(DosDimensiones dd){
        altura=dd.altura;
        base=dd.base;
        nombre=dd.nombre;
    }

    //Métodos de acceso para base y altura
    double getBase(){return base;}
    double getAltura(){return altura;}
    void setBase(double b){base=b;}
    void setAltura(double h){altura=h;}
    String getNombre(){return nombre;}

    void mostrarDimension(){
        System.out.println("La base y la altura son: "+base+" y "+altura);
    }

    double area(){
        return 0.0;
    }
}

La definición de area() es simplemente un marcador de posición (placeholder). No calculará ni mostrará el área de ningún tipo de objeto.

2. Método abstracto

Como verá, al crear tus propias bibliotecas de clases, no es raro que un método no tenga una definición significativa en el contexto de su superclase. Puedes manejar esta situación de dos maneras.

  1. Una forma es simplemente hacer que se muestre un mensaje de advertencia. Si bien este enfoque puede ser útil en determinadas situaciones, como la depuración, generalmente no es apropiado.
  2. Puede tener métodos que la subclase debe anular para que la subclase tenga algún significado.

Considera la clase Triangulo. Está incompleto si area() no está definida. En este caso, desea asegurarse de que una subclase, de hecho, anule todos los métodos necesarios. La solución de Java a este problema es el método abstracto.

Se crea un método abstracto al especificar el modificador de tipo abstract. Un método abstracto no contiene cuerpo y, por lo tanto, no está implementado por la superclase. Por lo tanto, una subclase debe anularla; no puede simplemente usar la versión definida en la superclase. Para declarar un método abstracto, use esta forma general:

abstract tipo nombre(lista-parámetros);

Como puede ver, no hay ningún cuerpo de método presente. El modificador abstract se puede usar solo en métodos de instancia. No se puede aplicar a métodos estáticos ni a constructores.

Una clase que contiene uno o más métodos abstractos también debe declararse como abstracta precediendo a su declaración de clase con el modificador abstract. Como una clase abstracta no define una implementación completa, no puede haber objetos de una clase abstracta. Por lo tanto, intentar crear un objeto de una clase abstracta usando new generará un error en tiempo de compilación.

Cuando una subclase hereda una clase abstracta, debe implementar todos los métodos abstractos en la superclase. Si no lo hace, entonces la subclase también se debe especificar como
abstracta.

Por lo tanto, el atributo abstract se hereda hasta el momento en que se logra una implementación completa.

3. Ejemplo en Java

Usando una clase abstracta, puede mejorar la clase DosDimensiones. Dado que no existe un concepto significativo de área para una figura bidimensional indefinida, la siguiente versión del programa declara area() como abstract dentro de DosDimensiones, y también DosDimensiones como abstract. Esto, por supuesto, significa que todas las clases derivadas de DosDimensiones deben anular area().

//Creando una clase abstracta
//DosDimensiones.java
abstract class DosDimensiones{
     private double base;
     private double altura;
     private String nombre;

     //Constructor por defecto
    DosDimensiones(){
        base=altura=0.0;
        nombre="ninguno";
    }

    //Parametrizando constructor
    DosDimensiones(double b, double h, String n){
        base= b;
        altura= h;
        nombre=n;
    }

    //Construir objeto con misma base y altura
    DosDimensiones(double x, String n){
        base=altura=x;
        nombre=n;
    }

    //Construir un objeto desde un objeto
    DosDimensiones(DosDimensiones dd){
        altura=dd.altura;
        base=dd.base;
        nombre=dd.nombre;
    }

    //Métodos de acceso para base y altura
    double getBase(){return base;}
    double getAltura(){return altura;}
    void setBase(double b){base=b;}
    void setAltura(double h){altura=h;}
    String getNombre(){return nombre;}

    void mostrarDimension(){
        System.out.println("La base y la altura son: "+base+" y "+altura);
    }

    //Ahora, area() es abstracta
    abstract double area();

}
//Extendiendo de DosDimensiones
//Triangulo.java
class Triangulo extends DosDimensiones{
    private String estilo;

    //Constructor por defecto
    Triangulo(){
        super();
        estilo="ninguno";
    }

    Triangulo(String s, double b, double h){
        super(b,h,"Triangulo");  //Llama al constuctor de la superclase
        estilo=s;
    }

    //Constructor con un argumento
    Triangulo(double x){
        super(x,"Triangulo"); //Llama al constuctor de la superclase
        estilo="Estilo 1";
    }

    //Construir un objeto desde un objeto
    Triangulo(Triangulo t){
        super(t); //Pasa el objeto al constructor de DosDimensiones
        estilo=t.estilo;
    }

    double area(){
        return getAltura()*getBase()/2;
    }

    void mostrarEstilo(){
        System.out.println("El triángulo tiene: "+estilo);
    }
}
//Una subclase de DosDimensiones para Rectángulo
class Rectangulo extends DosDimensiones {
    //Constructor por defecto
    Rectangulo(){
        super();
    }

    //Constructor para Rectangulo
    Rectangulo(double b, double h){
        super(b,h,"Rectangulo");
    }

    //Un cuadrado
    Rectangulo(double x){
        super(x,"Rectangulo");
    }

    //Objeto desde un objeto
    Rectangulo(Rectangulo ob){
        super(ob);
    }

    boolean esCuadrado(){
        if (getAltura()==getBase()) return true;
        return false;
    }

    double area(){
        return getBase()*getAltura();
    }
}

class Ejecutar{
public static void main(String[]args){
        DosDimensiones formas[]=new DosDimensiones[4];

        formas[0]=new Triangulo("Estilo 1",8.0,12.0);
        formas[1]=new Rectangulo(10);
        formas[2]=new Rectangulo(10,4);
        formas[3]= new Triangulo(7.0);

        for (int i=0; i<formas.length;i++){
            System.out.println("El objeto es: "+formas[i].getNombre());
            System.out.println("El área es: "+formas[i].area());

            System.out.println();
        }
 }
}

Salida:

El objeto es: Triangulo
El área es: 48.0

El objeto es: Rectangulo
El área es: 100.0

El objeto es: Rectangulo
El área es: 40.0

El objeto es: Triangulo
El área es: 24.5

Como lo ilustra el programa, todas las subclases de DosDimensiones deben anular area(). Para demostrarte esto, intenta crear una subclase que no anule area(). Recibirá un error en tiempo de compilación. Por supuesto, aún es posible crear una referencia de objeto de tipo DosDimensiones, que hace el programa. Sin embargo, ya no es posible declarar objetos del tipo DosDimensiones. Debido a esto, en main() la matriz de formas se ha reducido a 4 y ya no se crea un objeto DosDimensiones.

Un último punto: observe que DosDimensiones aún incluye los métodos mostrarDimension() y getNombre() y que estos no se modifican por abstract. Es perfectamente aceptable, de hecho, bastante común, que una clase abstracta contenga métodos concretos que una subclase es libre de usar tal cual. Solo los métodos declarados como abstractos deben ser reemplazados por subclases.

Clases en Java
  • Clase Abstract

Sobre el Autor:

Hey hola! Yo soy Alex Walton y tengo el placer de compartir conocimientos hacía ti sobre el tema de Programación en Java, desde cero, Online y Gratis.

Deja una Respuesta

*

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.