CodeGym /Cursos /JAVA 25 SELF /Diferencia entre interfaces y clases abstractas

Diferencia entre interfaces y clases abstractas

JAVA 25 SELF
Nivel 20 , Lección 1
Disponible

1. Clase abstracta: repasemos lo básico

Antes de pasar a la comparación, recordemos qué es una clase abstracta.

Una clase abstracta — es una clase que no puede crearse directamente (no se puede escribir new Animal()), pero puede contener tanto métodos normales (con implementación) como métodos abstractos (sin implementación). Una clase abstracta se usa a menudo como base para otras clases que heredan su comportamiento y/o están obligadas a implementar algunos métodos.

Por ejemplo, si en nuestra aplicación hay diferentes tipos de transporte, podemos crear la clase abstracta Transport:

public abstract class Transport {
    private String model;

    public Transport(String model) {
        this.model = model;
    }

    public String getModel() {
        return model;
    }

    // Método abstracto — no hay implementación, solo declaración
    public abstract void move();

    // Método normal — hay implementación
    public void printInfo() {
        System.out.println("Modelo de transporte: " + model);
    }
}

Características de la clase abstracta:

  • Puede contener campos (estado).
  • Puede contener métodos implementados.
  • Puede contener métodos abstractos (obligatorios de implementar en las subclases).
  • No se puede crear una instancia directamente.
  • Se utiliza para comportamiento y estado comunes.

2. Interfaz: repasemos lo básico

Una interfaz es un conjunto de métodos que una clase debe implementar. Una interfaz no describe estado (no puede tener campos normales, solo constantes) y no contiene implementaciones de métodos (hasta Java 8). Una interfaz es un contrato puro: «Si me implementas, estás obligado a saber hacer esto».

Ejemplo de interfaz:

public interface Movable {
    void move(int x, int y);
}

Características de la interfaz:

  • No contiene estado (solo constantes public static final).
  • Hasta Java 8 — solo métodos abstractos (desde Java 8 aparecieron métodos default y static, pero hablaremos de ellos más adelante).
  • Los métodos son siempre public abstract por defecto.
  • Una clase puede implementar varias interfaces.
  • Se utiliza para describir capacidades, «qué sabe hacer» la clase.

3. Tabla comparativa: clase abstracta vs interfaz

¡Es hora de compararlas cara a cara! Aquí tienes una tabla ilustrativa:

Característica Clase abstracta Interfaz
Sintaxis
abstract class
interface
¿Se puede crear una instancia? No No
¿Puede contener métodos normales? Hasta Java 8 — no; desde Java 8 — solo default/static
¿Puede contener métodos abstractos? Sí (todos los métodos hasta Java 8 son abstractos)
¿Puede contener campos (estado)? Sí (cualquier campo) Solo public static final (constantes)
¿Puede contener constructores? No
Herencia Solo una clase (abstracta o normal) Se pueden implementar varias interfaces
Modificadores de métodos Cualesquiera (public, protected, private) Los métodos por defecto son public abstract. Desde Java 9 se pueden añadir métodos private para uso dentro de la interfaz
Herencia mediante
extends
implements
Uso habitual Implementación y estado comunes Descripción de capacidades y roles
Ejemplos del JDK
AbstractList, AbstractMap
Comparable, Runnable

4. ¿Cuándo usar una interfaz y cuándo una clase abstracta?

Usa una interfaz cuando:

  • Quieres describir «qué sabe hacer» la clase sin preocuparte de cómo lo hace.
  • Necesitas que la clase pueda implementar varias capacidades independientes.
  • Ejemplo: Comparable (se puede comparar), Serializable (se puede serializar), Runnable (se puede ejecutar en un hilo).

Usa una clase abstracta cuando:

  • Quieres definir una implementación y un estado comunes que tendrán todas las subclases.
  • Necesitas que todas las subclases tengan ciertos campos o métodos con implementación.
  • La herencia es estrictamente «uno a uno»: una clase solo puede heredar de una única clase (normal o abstracta).

Analogías de la vida real

  • Interfaz — es como el «permiso de conducir»: si lo tienes, puedes conducir un coche, pero nadie dice en qué coche exactamente ni cómo lo haces.
  • Clase abstracta — es como el «plano general de un automóvil»: todos los coches tienen volante, pedales, motor, pero cada marca implementa los detalles a su manera.

5. Ejemplos de la biblioteca estándar de Java

Interfaz: Comparable

public interface Comparable<T> {
    int compareTo(T o);
}

Cualquier clase que implemente esta interfaz está obligada a implementar el método compareTo. Por ejemplo, String, Integer, LocalDate y muchas otras.

Clase abstracta: AbstractList

public abstract class AbstractList<E> implements List<E> {
    // Implementación por defecto de algunos métodos de List
    // Algunos métodos se dejan abstractos
}

AbstractList ya implementa parte del comportamiento de las colecciones (por ejemplo, métodos de añadir/eliminar), pero deja algunos métodos como abstractos para que las subclases puedan implementarlos a su manera.

6. Ejemplos de código: comparación en la práctica

Interfaz

Creemos una interfaz y una clase que la implemente.

public interface Printable {
    void print();
}

public class Document implements Printable {
    @Override
    public void print() {
        System.out.println("Imprimiendo documento...");
    }
}

Clase abstracta

Ahora, una clase abstracta y su subclase.

public abstract class Machine {
    public void turnOn() {
        System.out.println("La máquina está encendida.");
    }

    public abstract void work();
}

public class Printer extends Machine {
    @Override
    public void work() {
        System.out.println("La impresora está imprimiendo...");
    }
}

Una clase que usa ambos: interfaz y clase abstracta

public class SmartPrinter extends Machine implements Printable {
    @Override
    public void work() {
        System.out.println("La impresora inteligente está funcionando...");
    }

    @Override
    public void print() {
        System.out.println("La impresora inteligente está imprimiendo...");
    }
}

7. Implementación múltiple de interfaces: por qué es genial

En Java una clase solo puede heredar de una única clase (abstracta o normal), ¡pero puede implementar tantas interfaces como sea necesario! Esto permite crear arquitecturas flexibles y extensibles.

public interface Scannable {
    void scan();
}

public class MultiFunctionPrinter extends Machine implements Printable, Scannable {
    @Override
    public void work() {
        System.out.println("El multifunción está funcionando...");
    }

    @Override
    public void print() {
        System.out.println("El multifunción está imprimiendo...");
    }

    @Override
    public void scan() {
        System.out.println("El multifunción está escaneando...");
    }
}

¿Cuándo elegir qué?

  • Si estás diseñando funcionalidad base con estado común (por ejemplo, campos), usa una clase abstracta.
  • Si quieres añadir a los objetos «etiquetas de capacidades» (por ejemplo, «puede imprimir», «puede compararse», «puede serializarse»), usa interfaces.
  • Si no estás seguro, empieza con una interfaz. En Java se considera buena práctica: las interfaces dan mayor flexibilidad y extensibilidad.

8. Errores típicos y trampas

Error n.º 1: Intentas heredar de varias clases — ¡Java no te dejará!
Una clase puede heredar solo de una clase, pero implementar muchas interfaces. Por ejemplo, class A extends B, C — error, mientras que class A extends B implements X, Y, Z — sin problema.

Error n.º 2: Confundes campos de una interfaz y de una clase.
En una interfaz solo se pueden declarar constantes (public static final). No se puede declarar estado normal, por ejemplo, private int count; — el compilador te detendrá al instante.

Error n.º 3: No implementaste todos los métodos de la interfaz.
Si una clase no implementa al menos un método de la interfaz, debe declararse como abstract; de lo contrario, el compilador generará un error.

Error n.º 4: Intentas crear una instancia de una interfaz o de una clase abstracta.
Ambos tipos son «semielaborados». Solo se pueden extender, no instanciar directamente:

Printable p = new Printable(); // ¡Error!
Machine m = new Machine();     // ¡Error!

Error n.º 5: Piensas que una interfaz puede tener constructor.
Las interfaces no pueden tener constructores, ya que no describen el estado de los objetos. Solo las clases (normales y abstractas) pueden tenerlos.

1
Tarea
JAVA 25 SELF, nivel 20, lección 1
Bloqueada
Empresa de Transporte: Protocolo Unificado de Movimiento
Empresa de Transporte: Protocolo Unificado de Movimiento
1
Tarea
JAVA 25 SELF, nivel 20, lección 1
Bloqueada
Registro Universitario: Personas e Identificadores
Registro Universitario: Personas e Identificadores
1
Tarea
JAVA 25 SELF, nivel 20, lección 1
Bloqueada
Dispositivo multifunción de oficina
Dispositivo multifunción de oficina
1
Tarea
JAVA 25 SELF, nivel 20, lección 1
Bloqueada
Smartphone: De Dispositivos Generales a Gadgets Personales
Smartphone: De Dispositivos Generales a Gadgets Personales
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION