¿Por qué debería declarar una clase como una clase abstracta?

39

Sé la sintaxis, las reglas aplicadas a la clase abstracta y quiero saber el uso de una clase abstracta

  

La clase abstracta no puede ser instanciada directamente, pero puede ser extendida por otra clase

¿Cuál es la ventaja de hacerlo?

¿En qué se diferencia de una interfaz?

Sé que una clase puede implementar múltiples interfaces pero solo puede extender una clase abstracta. ¿Es esa la única diferencia entre una interfaz y una clase abstracta?

Soy consciente del uso de una interfaz. Lo he aprendido del modelo de delegación de eventos de AWT en Java.

¿En qué situaciones debería declarar la clase como una clase abstracta? ¿Qué ventajas tiene eso?

    
pregunta Vaibhav Jani 29.07.2011 - 10:59

9 respuestas

48

Esta respuesta hace un buen trabajo al explicar las diferencias entre una clase abstracta y una interfaz, pero no responde por qué debería declarar una.

Desde un punto de vista puramente técnico, nunca hay un requisito para declarar una clase como abstracta.

Considera las siguientes tres clases:

class Database { 
    public String[] getTableNames() { return null; } //or throw an exception? who knows...
}

class SqlDatabase extends Database { } //TODO: override getTableNames

class OracleDatabase extends Database { }  //TODO: override getTableNames

No tienes para hacer que la clase Base de datos sea abstracta, aunque hay un problema obvio con su implementación: cuando escribes este programa, puedes escribir new Database() y sería válido, pero nunca funcionaría.

En cualquier caso, todavía obtendrías polimorfismo, por lo que siempre que tu programa solo genere las instancias SqlDatabase y OracleDatabase , podrías escribir métodos como:

public void printTableNames(Database database) {
    String[] names = database.getTableNames();
}

Las clases abstractas mejoran la situación al evitar que un desarrollador cree una instancia de la clase base, porque un desarrollador lo ha marcado como que le falta funcionalidad . También proporciona seguridad en tiempo de compilación para que pueda asegurarse de que cualquier clase que extienda su clase abstracta proporcione la funcionalidad mínima para que funcione, y no debe preocuparse por poner métodos de código auxiliar (como el uno arriba) que los herederos de alguna manera deben saber mágicamente que tienen para anular un método para que funcione.

Interfaces son un tema totalmente separado. Una interfaz le permite describir qué operaciones se pueden realizar en un objeto. Normalmente, usará interfaces al escribir métodos, componentes, etc. que utilizan los servicios de otros componentes, objetos, pero no le importa de qué tipo de objeto real recibe los servicios.

Considera el siguiente método:

public void saveToDatabase(IProductDatabase database) {
     database.addProduct(this.getName(), this.getPrice());
}

No te importa si el objeto database hereda de un objeto en particular, solo te importa que tenga el método addProduct . Entonces, en este caso, una interfaz es más adecuada que hacer que todas sus clases se hereden de la misma clase base.

A veces la combinación de los dos funciona muy bien. Por ejemplo:

abstract class RemoteDatabase implements IProductDatabase { 
    public abstract String[] connect();
    public abstract void writeRow(string col1, string col2);

    public void addProduct(String name, Double price) {
        connect();
        writeRow(name, price.toString());
    }
}

class SqlDatabase extends RemoteDatabase {
    //TODO override connect and writeRow
}

class OracleDatabase extends RemoteDatabase { 
    //TODO override connect and writeRow
}

class FileDatabase implements IProductDatabase {
    public void addProduct(String name, Double price) {
         //TODO: just write to file
    }
}

Observe cómo algunas de las bases de datos heredan de RemoteDatabase para compartir alguna funcionalidad (como conectarse antes de escribir una fila), pero FileDatabase es una clase separada que solo implementa IProductDatabase .

    
respondido por el Kevin McCormick 13.06.2012 - 22:12
15

Similitudes

Se requieren clases e interfaces abstractas para la abstracción. No se pueden crear instancias con un nuevo , pero se pueden resolver mediante la inversión de contenedores de control o mediante patrones de fábrica.

Diferencia

  1. Interfaces

    • Defina un contrato público bien conocido, habilidades del tipo
    • Aplicable para mostrar la herencia horizontal, es decir, se ramifica en el primer nivel de herencia (por ejemplo, ILog para definir las instalaciones de registro en la base de datos, archivo de texto, XML, SOAP, etc.)
    • Todos los miembros son públicos
    • No se permite implementación
    • El hijo de herencia puede tener muchas interfaces para implementar
    • Útil para la integración de terceros
    • Los nombres generalmente comienzan con I
  2. clase abstracta

    • Defina la estructura, la identidad y algunos comportamientos admitidos por defecto
    • Aplicable para mostrar la herencia vertical, es decir, la ramificación profunda en varios niveles (por ejemplo, la clase AbstractEntity en el desarrollo dirigido por dominio)
    • Los miembros pueden tener una visibilidad diferente (de público a privado)
    • Puede implementar algunos miembros (por ejemplo, * clases de Reader)
    • El hijo de herencia solo puede tener una clase abstracta base

En realidad, es fácil encontrar la respuesta en simple consulta de google .

    
respondido por el oleksii 29.07.2011 - 11:31
11
  

¿En qué se diferencia de una interfaz?

En una clase abstracta, puede implementar algunos métodos y dejar (forzar) el resto para que sea implementado por la clase extendida. No se pueden implementar métodos en una interfaz. No puedes obligar a nadie a anular nada al extender una clase ordinaria. Con una clase abstracta, puedes.

    
respondido por el Joonas Pulakka 29.07.2011 - 11:08
8

Las clases abstractas son para "es un" las relaciones y las interfaces son para "se puede hacer".

Las clases abstractas te permiten agregar un comportamiento básico para que los programadores no tengan que codificar todo, mientras que los obliga a seguir tu diseño.

    
respondido por el Tulains Córdova 16.08.2012 - 15:00
3

Además de los detalles técnicos profundos, como la implementación de algunos métodos para clases abstractas, etc., el significado es el siguiente:

Las interfaces definen la capacidad común: IEnumerable define, que la clase que implementa esta interfaz se puede enumerar. No dice nada sobre la clase en sí.

Las clases abstractas (o básicas) definen el comportamiento: WebRequest define un comportamiento común de todas las clases secundarias como HttpWebRequest, etc. Define el significado principal de la clase y su propósito real: acceder a los recursos web.

    
respondido por el Sunny 29.07.2011 - 18:23
2

entrada de Wikipedia .

Las principales diferencias entre una interfaz y una clase abstracta es que una clase abstracta puede proporcionar métodos implementados. Con las interfaces solo puede declarar métodos, escribir su firma. Aquí hay un ejemplo de una clase que extiende una clase abstracta que implementa dos interfaces: (java)

interface MyInterface1 {
  string getValue1();
}

interface MyInterface2 {
  string getValue2();
}

abstract class MyAbstractClass implements MyInterface1, MyInterface2{
  void printValues() {
    System.out.println("Value 1: " + getValue1() + ", Value 2: " + getValue2() + 
                       ", Value 3: " + getValue3());
  }

  protected abstract string getValue3();
}

class ImpClass extends MyAbstractClass {
  public string getValue1() {
    return "1";
  }

  public string getValue2() {
    return "2";
  }

  protected string getValue3() {
    return "3";
  }
}

En este ejemplo, MyAbstractClass proporciona un método público que imprime los tres valores. En ImpClass necesita implementar getValue1 y getValue2 respectivamente desde MyInterface1 y MyInterface2 y getValue3 de la clase abstracta.

Voilà.

Hay más aspectos (interfaz: solo métodos públicos, clase abstracta: métodos abstractos protegidos y abstractos públicos), pero puedes leerlo por ti mismo.

En una nota final, una clase abstracta que solo proporciona métodos abstractos es una clase base abstracta "pura", también conocida como interfaz.

    
respondido por el Jalayn 29.07.2011 - 11:17
2
  • Interfaz: cuando algunas clases comparten una API (nombres de método y parámetros)
  • Clase abstracta: cuando algunas clases comparten el mismo código (implementación)

En otras palabras, debe comenzar con una pregunta: "¿estas clases necesariamente comparten la implementación , o simplemente tienen una interfaz ?"

Si la respuesta es mixta, como - estas tres clases deben compartir la implementación, pero estas otras dos solo comparten su API - entonces puede crear una interfaz para las cinco y una clase abstracta para esas tres. con el código común.

También hay otras formas de compartir la implementación, por ejemplo, para encapsular un objeto con esa implementación (por ejemplo, en el patrón Strategy ).

    
respondido por el Viliam Búr 17.08.2012 - 10:35
1

Declararías un resumen de clase cuando no quieras que el desarrollador (probablemente tú mismo) tenga una instancia, porque no funcionaría o no tendría sentido.

Por ejemplo, considera un juego donde hay diferentes tipos de entidades de juego. Todos heredan de la clase base GameEntity .

abstract class GameEntity{

    int lifePoint, speed, damage;

    public attack(GameEntity target){ target.damage(damage); }

    public damage(int damageInflicted){ lifePoint -= damageInflicted - speed; }

    // etc...

}

Esta clase se declara abstract ya que no tendría sentido instanciarla. Declara algunas acciones para las entidades del juego y algunos atributos, pero en ninguna parte de esta clase se inicializan estos atributos. Esta clase sirve como plantilla para las entidades del juego, pero no está diseñada para ser instanciada por sí misma y, como tal, declarada abstract .

Con respecto a la diferencia de uso entre una clase abstracta y una interfaz:

Tal como lo veo, una interfaz es una forma de obtener un comportamiento polimórfico sin estar limitado por el mecanismo de herencia única de algunos idiomas.

Volvamos al juego como ejemplo. Considere una clase Enemy que se deriva de GameEntity . Esta clase tiene un método attackMeFromDistance(RangedAttacker attacker) . Este método está destinado a permitir que las entidades ataquen al enemigo desde lejos.

Como puede ver, este método toma un tipo RangedAttacker como parámetro. Sin embargo, todas las entidades del juego ya heredan de GameEntity . No pueden extender otra clase.

Toma las clases Mage y Archer , por ejemplo. Queremos permitir que ambos sean aceptados como parámetros en el método attackMeFromDistance(RangedAttacker attacker) , pero ya se derivan de GameEntity .

Para resolver esto, creamos una nueva interfaz:

interface RangedAttacker{
    public void attackFromDistance();
}

Una clase que implementa esta interfaz debe implementar el método attackFromDistance() , y por lo tanto se asegura que tiene capacidades de ataque de rango. Esto significa que el método attackMeFromDistance ahora puede aceptar de forma segura las clases que implementan esta interfaz. Entonces, hacer que Mage y Archer implementen esa interfaz resuelve nuestro problema.

Para mí, este es el poder de las interfaces.

Para resumir, usualmente usaría una clase abstracta cuando quiere tener una clase base para algunas clases, pero no tendría sentido instanciarla por sí misma (o en el caso de que tenga abstract métodos, que deben ser implementados por las subclases, y en este caso el compilador le obligaría a hacer la clase abstract ). Usaría una interfaz para obtener un comportamiento polimórfico sin estar limitado por el mecanismo de herencia única.

    
respondido por el Aviv Cohn 14.04.2014 - 12:40
0
  1. Existe la posibilidad de que muy pocos métodos sean comunes a alguna clase (lógica empresarial). Y los métodos restantes son diferentes. En ese tipo de escenarios, puede implementar todos los métodos comunes en una clase y declarar los restantes como abstractos. Entonces deberías declarar la clase como abstracta.
  2. A veces no permites crear el objeto directamente a la clase. Ese tipo de clase necesita declarar la clase como abstracta.
respondido por el Dharani Kumar 12.10.2012 - 20:34

Lea otras preguntas en las etiquetas