george_curious
george_curious

Reputation: 49

Functional Interface Object Cast

I've encountered the following code in a Java project, and I'm not sure what to make of it:

public Function<CustomEnum,String> foo(SomeObject someObject) {
    return ((Function<CustomEnum,String>) (someObject::toString)).andThen(r -> someObject::getSomethingWithEnumParameter);
}

I don't really understand how you can cast something to a Functional Interface. What does that even mean?

Isn't the resulting type of the return value going to be whatever value someObject.

Isn't Function<CustomEnum, String> defining an anonymous function that takes a type CustomEnum and returns a String?

I've read the java doc for Function<T,R>, and to be honest, this doesn't make much more sense than before I read the document.

This is what I believe is happening.

  1. foo is returning an anonymous function that is applied to some CustomEnum to return a String

  2. the anonymous function inside of foo (which is somehow cast onto someObject::toString, which I don't understand) is applied to the CustomEnum that will be passed from the initial call of foo(someObject).apply(customEnum).

  3. The andThen will take the resulting String from the anonymous function inside of foo (which was cast somehow I still don't understand), and then return the value of someObject::getSomethingWithEnumParameter. Why isn't the return type just the type of someObject::getSomethingWithEnumParameter, which we'll say is a Map<R,T>, for sake of discussion.

If anyone could help me understand this flow, I would greatly appreciate it.

Upvotes: 0

Views: 1144

Answers (1)

jon hanson
jon hanson

Reputation: 9408

In an ideal world this would work:

public Function<CustomEnum,String> foo(SomeObject someObject) {
    return (someObject::toString).andThen(...);
}

However Java needs an interface type in order to implicitly create an interface instance from the method reference., hence the explicit cast is required to cast to the Function interface type.

Once you have an instance of Function then you can call any method on it as per normal, in this case the andThen method which composes it with another function object to form a new function.

Breaking it down:

someObject::toString is a method reference with implied type Function<CustomEnum, String>. I.e. toString is a method on SomeObject which takes a parameter of type CustomEnum and returns a String.

r -> someObject::getSomethingWithEnumParameter has the wrong type though - it's a function which returns a function. If you get rid of the "r ->" part then it is valid, as long as someObject::getSomethingWithEnumParameter is a method on SomeObject that takes a String and returns a String. Alternatively the return type of foo would need to change to Function<CustomEnum, Function<String, String>>.

If you combine those two with andThen then you have a Function which takes a CustomEnum and returns a String, as pr the return type of foo.

Upvotes: 2

Related Questions