Skip to content
Advertisement

Trying to mimic java functional interface

I am trying to mimic the java’s Function<T,R> by writing below code :

interface SFunction<T, G> {
    G apply(T t);

    default <Q> SFunction<T, Q> andThen(SFunction<? super G, ? extends Q> after) {
       return (T t) -> {
            return after.apply(apply(t));
        };
        // return new SFunction<T, Q>() {
        // @Override
        // public Q apply(T t) {
        // return after.apply(apply(t));
        // }
        // };
    }
}

when I am writing below code in andThen, it’s working fine (pointing to apply(T t) of interface) and perfectly chaining the other functional implementations

snippet A return (T t) -> {
    return after.apply(apply(t));     
};

But when writing below snippet, it’s falling into recursion, logically that’s correct

snippet B return new SFunction<T, Q>() {
            @Override
            public Q apply(T t) {
                return after.apply(apply(t));
            }
        };

, but why in snippet A, after.apply(apply(t)) is calling outer apply(T t) even though internally java implement the anonymous implementation.

Isn’t snippet A and B same internally and logically?

Thanks

Advertisement

Answer

It is important to note what method the apply(t) in snippet B is actually referring to:

@Override
public Q apply(T t) { // <--- it's referring to this method!
    return after.apply(apply(t));
//                     ^^^^^^^^
}

It is actually referring to the apply(T) method that returns a Q that you have just declared. It’s trying to call it recursively. But obviously that doesn’t work, because after.apply doesn’t expect a Q. The declaration of the Q apply(T) method shadows the G apply(T) method declared outside.

In the lambda’s case, you do not introduce a new identifier called apply, so apply can only mean the apply on the SFunction<T, G> object – the one on which andThen is called.

To refer to the SFunction<T, G> object’s apply method in the SFunction<T, Q> anonymous class, you can use a qualified this expression:

return after.apply(SFunction.this.apply(t));

SFunction.this refers to the SFunction<T, G> object on which andThen is called.

Now the two versions are logically the same, but internally, lambdas are very different from anonymous classes.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement