Una clase abstracta no puede instanciarse directamente. Define un contrato parcial: puede mezclar métodos abstractos (que las subclases deben implementar) con métodos concretos (implementación compartida).
public abstract class Figura {
private String color; // campo de instancia ✓
public Figura(String color) { this.color = color; } // constructor ✓
public abstract double calcularArea(); // obliga a implementar
public abstract double calcularPerimetro();
public String getColor() { return color; } // implementación compartida
}Diferencia clave con interfaces: una clase solo puede extender una clase abstracta, pero puede implementar múltiples interfaces.
| Característica | Clase Abstracta | Interfaz |
|---|---|---|
| Instanciable | No | No |
| Herencia | Simple (una) | Múltiple |
| Métodos con estado | Sí (campos de instancia) | No (constantes) |
| Constructores | Sí | No |
| Métodos concretos | Sí | Sí (default, Java 8+) |
| Modificadores acceso | Cualquiera | public (implícito) |
Cuándo usar clase abstracta:
- Quieres compartir código y estado entre clases relacionadas.
- Necesitas constructores con lógica común.
- Las subclases comparten una relación "es-un" fuerte.
Cuándo usar interfaz:
- Quieres definir un contrato que clases no relacionadas pueden implementar.
- Necesitas herencia múltiple de comportamiento.
- Modelas capacidades (
Comparable,Serializable,Runnable).
- Compartir implementación entre clases con relación jerárquica.
- Forzar a las subclases a implementar métodos específicos del dominio.
- Permite campos de instancia y constructores (imposible en interfaces).
- Combina reutilización de código con polimorfismo.
Ver ExpAbstractVsInterface.java, ExpAbstractSealed.java, ExpInheritanceVsComposition.java, ExpAbstractFactory.java y ExpTemplateMethod.java para ejemplos ejecutables con clases abstractas, interfaces, herencia, composición y patrones relacionados.