Semana 10 - Interfaces en Java.
1. ¿Qué es una interfaz en Java?
- Una interfaz es una colección de métodos abstractos (sin implementación) y, opcionalmente, constantes (campos estáticos y finales), métodos por defecto, métodos estáticos y métodos privados (a partir de Java 9).
- Se declara usando la palabra clave
interface
. - Las clases que implementan una interfaz deben proporcionar la implementación de todos sus métodos abstractos, a menos que la clase sea abstracta.
- Las interfaces son una forma de garantizar que las clases sigan un comportamiento estándar sin preocuparse por cómo se implementa.
Sintaxis básica:
public interface NombreInterfaz {
// Constantes (opcional)
public static final int CONSTANTE = 10;
// Métodos abstractos (sin cuerpo)
void metodoAbstracto();
// Método por defecto (Java 8+)
default void metodoPorDefecto() {
System.out.println("Este es un método por defecto");
}
// Método estático (Java 8+)
static void metodoEstatico() {
System.out.println("Este es un método estático");
}
}
2. Características clave de las interfaces
- Abstracción total: Todos los métodos en una interfaz son abstractos por defecto (a menos que sean
default
ostatic
), lo que significa que no tienen implementación. - Implementación múltiple: Una clase puede implementar múltiples interfaces, lo que permite simular la herencia múltiple en Java.
- No tienen constructores: Las interfaces no pueden ser instanciadas directamente (
new NombreInterfaz()
no es válido). - Campos constantes: Los campos en una interfaz son implícitamente
public
,static
yfinal
(constantes). - Métodos por defecto (Java 8+): Permiten agregar métodos con implementación sin romper las clases que ya implementan la interfaz.
- Métodos estáticos (Java 8+): Pueden ser llamados directamente desde la interfaz sin necesidad de una instancia.
- Métodos privados (Java 9+): Útiles para compartir lógica interna entre métodos por defecto o estáticos dentro de la interfaz.
- Herencia entre interfaces: Una interfaz puede extender otras interfaces usando la palabra clave
extends
.
3. Reglas para interfaces
- Una clase que implementa una interfaz debe usar la palabra clave
implements
. - Si una clase no implementa todos los métodos abstractos de la interfaz, debe declararse como
abstract
. - Los métodos de una interfaz son implícitamente
public
yabstract
(no es necesario especificarlo). - Una interfaz puede ser implementada por cualquier número de clases.
- No se pueden declarar variables de instancia ni métodos no abstractos (salvo
default
ostatic
).
4. Ejemplo básico de una interfaz
Supongamos que queremos definir un comportamiento para vehículos. Creamos una interfaz Vehiculo
y luego la implementamos en clases concretas.
// Definición de la interfaz
public interface Vehiculo {
// Método abstracto
void acelerar();
// Método abstracto
void frenar();
// Método por defecto
default void mostrarEstado() {
System.out.println("El vehículo está funcionando.");
}
// Método estático
static void informacionGeneral() {
System.out.println("Los vehículos pueden acelerar y frenar.");
}
}
// Clase que implementa la interfaz
public class Coche implements Vehiculo {
@Override
public void acelerar() {
System.out.println("El coche está acelerando.");
}
@Override
public void frenar() {
System.out.println("El coche está frenando.");
}
}
// Clase que implementa la interfaz
public class Bicicleta implements Vehiculo {
@Override
public void acelerar() {
System.out.println("La bicicleta está pedaleando más rápido.");
}
@Override
public void frenar() {
System.out.println("La bicicleta está frenando.");
}
}
// Clase principal para probar
public class Main {
public static void main(String[] args) {
// Crear instancias
Vehiculo coche = new Coche();
Vehiculo bicicleta = new Bicicleta();
// Llamar métodos
coche.acelerar(); // Salida: El coche está acelerando.
coche.frenar(); // Salida: El coche está frenando.
coche.mostrarEstado(); // Salida: El vehículo está funcionando.
bicicleta.acelerar(); // Salida: La bicicleta está pedaleando más rápido.
bicicleta.frenar(); // Salida: La bicicleta está frenando.
bicicleta.mostrarEstado(); // Salida: El vehículo está funcionando.
// Llamar método estático
Vehiculo.informacionGeneral(); // Salida: Los vehículos pueden acelerar y frenar.
}
}
Explicación del ejemplo:
- La interfaz Vehiculo
define un contrato con los métodos acelerar
, frenar
, un método por defecto mostrarEstado
y un método estático informacionGeneral
.
- Las clases Coche
y Bicicleta
implementan la interfaz, proporcionando su propia implementación de los métodos abstractos.
- En el método main
, usamos polimorfismo al declarar variables de tipo Vehiculo
que hacen referencia a objetos de tipo Coche
y Bicicleta
.
5. Implementación múltiple de interfaces
Java no permite herencia múltiple de clases, pero sí permite que una clase implemente múltiples interfaces. Esto es útil para combinar comportamientos de diferentes contratos.
Ejemplo:
// Interfaz 1
public interface Volador {
void volar();
}
// Interfaz 2
public interface Terrestre {
void conducir();
}
// Clase que implementa ambas interfaces
public class AvionAnfibio implements Volador, Terrestre {
@Override
public void volar() {
System.out.println("El avión anfibio está volando.");
}
@Override
public void conducir() {
System.out.println("El avión anfibio está navegando en el agua.");
}
}
// Clase principal
public class Main {
public static void main(String[] args) {
AvionAnfibio avion = new AvionAnfibio();
avion.volar(); // Salida: El avión anfibio está volando.
avion.conducir(); // Salida: El avión anfibio está navegando en el agua.
}
}
Explicación:
- La clase AvionAnfibio
implementa dos interfaces: Volador
y Terrestre
.
- Debe proporcionar implementaciones para todos los métodos abstractos de ambas interfaces.
6. Herencia entre interfaces
Una interfaz puede extender otra interfaz, heredando sus métodos. Esto permite crear jerarquías de interfaces.
Ejemplo:
// Interfaz base
public interface Animal {
void comer();
}
// Interfaz que extiende Animal
public interface Mamifero extends Animal {
void amamantar();
}
// Clase que implementa Mamifero
public class Perro implements Mamifero {
@Override
public void comer() {
System.out.println("El perro está comiendo.");
}
@Override
public void amamantar() {
System.out.println("El perro está amamantando a sus crías.");
}
}
// Clase principal
public class Main {
public static void main(String[] args) {
Perro perro = new Perro();
perro.comer(); // Salida: El perro está comiendo.
perro.amamantar(); // Salida: El perro está amamantando a sus crías.
}
}
Explicación:
- La interfaz Mamifero
extiende Animal
, por lo que incluye el método comer
además de su propio método amamantar
.
- La clase Perro
debe implementar ambos métodos.
9. Diferencias entre interfaces y clases abstractas
Característica | Interfaz | Clase Abstracta |
---|---|---|
Métodos | Solo abstractos, por defecto o estáticos | Puede tener métodos abstractos y concretos |
Herencia múltiple | Sí (una clase puede implementar varias) | No (solo una clase padre) |
Campos | Solo constantes (public static final ) |
Puede tener variables de instancia |
Constructores | No tiene constructores | Puede tener constructores |
Uso | Definir contratos puros | Proveer implementación parcial |