package ch.claude_martin.lambda; import java.lang.reflect.Constructor; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; import java.util.function.UnaryOperator; /** * A {@link Function} that returns a null of type Void. * *

* This is to demonstrate why a {@link Consumer} isn't also a {@link Function}. *

* This interface could come handy if you need a collection of functional methods that are all of * type {@link Function} but you want to include some {@link Consumer}s. *

* {@link UnaryOperator} is a Function as it has a return value, but a {@link Consumer} does not * return anything. There exists a member {@link #VOID} that references an instance of {@link Void} * or null and can be used as the returned value. *

* The same is true for similar Types such as Supplier. There you'd have to pass something to * {@link Supplier#get() get}. */ @FunctionalInterface public interface ConsumerFunction extends Function { /** * {@inheritDoc} * * @returns instance of {@link Void} or null */ public Void apply(T t); /** @see Consumer#accept(Object) */ default public void accept(final T t) { apply(t); } /** Convert this object to a regular {@link Consumer}. */ default public Consumer toConsumer() { return ConsumerFunction.this::apply; } /** * This instance of {@link Void} can be used as the returned value. It is null if no instance * could be created. */ public static final Void VOID = ((Supplier) () -> { try { final Constructor constructor = Void.class.getDeclaredConstructor(); constructor.setAccessible(true); return constructor.newInstance(); } catch (Throwable t) { return null; } }).get(); /** Convert some {@link Consumer} to a {@link Function}. */ public static ConsumerFunction toFunction(final Consumer consumer) { return t -> { consumer.accept(t); return VOID; }; } /** @see Consumer#andThen(Consumer) */ default ConsumerFunction andThen(final ConsumerFunction after) { Objects.requireNonNull(after); return (T t) -> { apply(t); after.apply(t); return VOID; }; } /** @see Consumer#andThen(Consumer) */ default Consumer andThen(final Consumer after) { Objects.requireNonNull(after); return (T t) -> { apply(t); after.accept(t); }; } }