Las interfaces son un elemento fundamental en la programación orientada a objetos. Facilitan la separación entre la definición de tareas y su implementación concreta.
Este capítulo se enfoca en explicar qué son las interfaces, cómo funcionan y por qué son una herramienta valiosa en el diseño de software robusto y flexible.
Una interfaz es un archivo que define operaciones (y propiedades constantes). sin implementar ninguna (hay lenguajes que hoy en día sí permiten crear implementaciones default, pero escapa al concepto de interfaz).
Define un contrato, que las clases que concretas que la implementan deben seguir, especificando qué se debe hacer pero no cómo se debe hacer.
Puede que en principio no se le vea sentido, agregar una capa más? que no hace nada? para qué?… Pero lo que no se ve es el potencial que ofrece, las interfaces son los puntos de comunicación entre capas… permiten que un objeto tome la forma de la interfaz… invertir dependencia, aislar partes, hacerlo extensible… es lo que permite diseñar, armar la arquitectura de un buen sistema que sea fácil de mantener y hacer crecer. Aquí está la importancia de las interfaces, polimorfismo puro.
En UML a la interfaz se le suele agregar encima del nombre el texto <<interface>>. También se escriben el nombre de la clase y los métodos en itálica.
Para el caso de Figura, nuestro diseño también podría verla como una interfaz que declara el método dibujar(), para que cada clase que la implemente lo redefina.

Las interfaces son definidas usando la palabra clave interface y tienen todos sus métodos sin implementar.
public interface Pagable {
void pagar(double cantidad);
}
En este ejemplo, cualquier clase que implemente Pagable debe proporcionar una implementación para el método pagar.
A diferencia de la herencia, Java permite que una clase implemente múltiples interfaces, proporcionando una especie de herencia múltiple, tomando varias formas.
Esto permite que una clase tenga varios contratos de interfaces.
Definimos una interfaz Identificable:
public interface Identificable {
String getId();
}
Usamos dos interfaces en esta clase, una para obtener el id, otra para pagar:
public class Pedido implements Pagable, Identificable {
// Implementación de ambos métodos
@Override
public void pagar(double cantidad) {
// Lógica de pago
}
@Override
public String getId() {
// Lógica para obtener ID
return "12345";
}
}
Lo destacable de esto es que un objeto de tipo Pedido puede ser tratado como un objeto de tipo Pedido, de tipo Pagable o de tipo Identificable.
Consideremos un e-commerce, que necesita manejar diferentes tipos de pagos, como tarjeta de crédito, PayPal y cupones.
Podemos definir una interfaz SistemaDePago y luego implementar esta interfaz para cada tipo de sistema de pago.
Definimos la Interfaz de Sistema de Pago:
public interface SistemaDePago {
void procesarPago(double cantidad);
}
Implementamos la interfaz para los 3 tipos de pago concretos:
public class PagoTarjetaCredito implements SistemaDePago {
@Override
public void procesarPago(double cantidad) {
System.out.println("Pago TC por: $" + cantidad);
}
}
public class PagoPayPal implements SistemaDePago {
@Override
public void procesarPago(double cantidad) {
System.out.println("Pago con PayPal por: $" + cantidad);
}
}
public class PagoCupon implements SistemaDePago {
@Override
public void procesarPago(double cantidad) {
System.out.println("Aplicando cupón de: $" + cantidad);
}
}
Creamos el carrito de compras que usa el sistema de pagos:
public class CarritoDeCompras {
public void procesarCompra(SistemaDePago sistemaPago, double cantidad) {
sistemaPago.procesarPago(cantidad);
}
}
Usamos la interfaz y el carrito de compras (puede ser en el método main):
// En el método main o cualquier otro método de prueba
CarritoDeCompras carrito = new CarritoDeCompras();
SistemaDePago tarjeta = new PagoTarjetaCredito();
SistemaDePago paypal = new PagoPayPal();
carrito.procesarCompra(tarjeta, 100.0);
carrito.procesarCompra(paypal, 75.0);
Las interfaces son una herramienta poderosa que facilitan la separación de la definición y la implementación, permitiendo un diseño más flexible y mantenible.
Al definir contratos claros a través de interfaces y permitir que las clases implementen múltiples interfaces, se pueden construir sistemas complejos y robustos con componentes intercambiables y fácilmente extensibles, son una herramienta fundamental en el diseño y arquitectura del sistema, y es el punto de comunicación con otras capas.
Comprender y utilizar interfaces es esencial para cualquier programador que busque escribir código limpio y modular.