I'm currently reading Functional Programming in Java by Venkat Subramaniam and so far its been a great read.
There is a particular example however that is causing me some confusion. In the code example below there is a method called setFilters(final Function<Color,Color>... filters).
This expects a list implementing the Function interface. In the code setFilters is called using method references ... camera.setFilters(Color::lighter, Color::darker);.
This is confusing because the Color class does not implement the Function interface and nor does it have a method that matches the R apply(T t); signature.
Have I missed something obvious here? Can someone please explain how Color::darker etc can be passed into a parameter that expects Function<Color,Color>
Here is the full code example:
package designing.fpij;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import java.util.stream.Stream;
import java.util.function.Function;
import java.awt.Color;
import java.util.function.Consumer;
@SuppressWarnings("unchecked")
public class Camera {
private Function<Color, Color> filter;
public Color capture(final Color inputColor) {
final Color processedColor = filter.apply(inputColor);
return processedColor;
}
public void setFilters(final Function<Color, Color>... filters) {
filter =
Stream.of(filters).
reduce((after, before) -> filter.compose(before)).orElse(color -> color);
}
public Camera() {
setFilters();
}
public static void main(final String[] args) {
final Camera camera = new Camera();
final Consumer<String> printCaptured = (filterInfo) ->
System.out.println(String.format("with %s: %s", filterInfo, camera.capture(new Color(200, 100, 150))));
System.out.println("//" + "START:NOFILTER_OUTPUT");
printCaptured.accept("no filter");
System.out.println("//" + "END:NOFILTER_OUTPUT");
System.out.println("//" + "START:BOTH_OUTPUT");
camera.setFilters(Color::brighter, Color::darker);
printCaptured.accept("brighter & darker filter");
System.out.println("//" + "END:BOTH_OUTPUT");
}
}
Calling
camera.setFilters(Color::darker);
is the equivalent of
setFilters(new Function<Color, Color>() {
@Override
public Color apply(Color color) {
return color.darker();
}
});
(if you were using pre-Java-8 anonymous inner classes). You can see when you add all the boilerplate that Color does not need to be a FunctionalInterface or implement Function - in the longer form you would be wrapping a call to this method inside a Function.
Simplifying this call to a lambda gives
setFilters((Function<Color, Color>) color -> color.darker());
or even shorter:
setFilters(color -> color.darker());
which ultimately can be simplified into your method reference:
setFilters(Color::darker);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With