Menu
Coddy logo textTech

Interfaces Funcionales

Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 39 de 87.

Una interfaz funcional es una interfaz que contiene exactamente un método abstracto. Esta restricción de un único método hace que las interfaces funcionales sean especiales porque pueden implementarse utilizando expresiones lambda, lo que permite un estilo de codificación más conciso.

Java proporciona la anotación @FunctionalInterface para marcar explícitamente una interfaz como funcional. Aunque es opcional, esta anotación ayuda al compilador a detectar errores si accidentalmente añades un segundo método abstracto:

@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
}

Puedes implementar una interfaz funcional de la forma tradicional con una clase, o de forma más concisa con una expresión lambda:

// Implementación tradicional
Calculator adder = new Calculator() {
    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
};

// Expresión lambda (¡mucho más corta!)
Calculator adder = (a, b) -> a + b;

System.out.println(adder.calculate(5, 3));  // 8

Las interfaces funcionales aún pueden tener métodos predeterminados y métodos estáticos, ya que estos no cuentan para la regla del único método abstracto. El paquete java.util.function de Java proporciona muchas interfaces funcionales integradas como Predicate, Function y Consumer que encontrarás con frecuencia al trabajar con flujos y colecciones.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de transformación de cadenas utilizando interfaces funcionales y expresiones lambda. Crearás un procesador de texto flexible que puede aplicar diferentes transformaciones a las cadenas, todo impulsado por una única interfaz funcional.

Organizarás tu código en tres archivos:

  • StringTransformer.java: Define una interfaz funcional que represente cualquier operación de transformación de cadenas. Márcala con la anotación @FunctionalInterface para asegurar que siga siendo funcional. Tu interfaz debe declarar un único método abstracto llamado transform que reciba un String y devuelva un String.
  • TextProcessor.java: Crea una clase que utilice tu interfaz funcional para procesar texto. Debe tener un campo para almacenar un StringTransformer y un constructor para inicializarlo. Incluye un método llamado process(String text) que aplique el transformador al texto dado y devuelva el resultado. Este diseño te permite inyectar cualquier comportamiento de transformación a través del constructor.
  • Main.java: Une todo creando diferentes transformaciones mediante expresiones lambda. Recibirás dos entradas: una cadena de texto y un tipo de operación (upper, lower, o reverse).

    Basándote en el tipo de operación, crea un TextProcessor con la lambda adecuada:

    • upper: transforma el texto a mayúsculas
    • lower: transforma el texto a minúsculas
    • reverse: invierte el texto (pista: usa StringBuilder)

    Luego llama a process() con el texto de entrada e imprime el resultado en este formato: Result: [transformed text]

Recibirás dos entradas: el texto a transformar (String) y el tipo de operación (String).

Observa cómo la misma clase TextProcessor puede realizar operaciones completamente diferentes dependiendo de qué lambda le pases; ¡ese es el poder de las interfaces funcionales!

Hoja de referencia

Una interfaz funcional es una interfaz con exactamente un método abstracto. Puede implementarse utilizando expresiones lambda para obtener un código conciso.

Utilice la anotación @FunctionalInterface para marcar una interfaz como funcional (opcional pero recomendado):

@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
}

Las interfaces funcionales pueden implementarse de forma tradicional o con expresiones lambda:

// Implementación tradicional
Calculator adder = new Calculator() {
    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
};

// Expresión lambda
Calculator adder = (a, b) -> a + b;

System.out.println(adder.calculate(5, 3));  // 8

Las interfaces funcionales pueden tener métodos predeterminados (default) y estáticos sin violar la regla del único método abstracto.

El paquete java.util.function de Java proporciona interfaces funcionales integradas como Predicate, Function y Consumer.

Pruébalo tú mismo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String text = scanner.nextLine();
        String operation = scanner.nextLine();
        
        TextProcessor processor;
        
        // TODO: Basado en el tipo de operación, crea un TextProcessor con la lambda apropiada:
        // - "upper": transforma el texto a mayúsculas
        // - "lower": transforma el texto a minúsculas
        // - "reverse": invierte el texto (pista: usa StringBuilder)
        
        // TODO: Llama a process() con el texto de entrada e imprime el resultado
        // Formato de salida: "Result: [transformed text]"
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos