如何同时实现Function和BiFunction?

时间:2016-01-08 04:35:54

标签: java function inheritance interface java-8

我创建了一个实现GenericFunctionFunction的课程BiFunction。但它无法编译。

public class GenericFunction<T, U, R> implements
        Function<T, R>, BiFunction<T, U, R> {

    @Override
    public R apply(T t, U u) {
        return null;
    }

    @Override
    public R apply(T t) {
        return null;
    }

}

错误消息是:

src\obscure\test\GenericFunction.java:6: error:
types BiFunction<T,U,R> and Function<T,R> are incompatible;
both define andThen(java.util.function.Function<? super R,? extends V>),
but with unrelated return types
public class GenericFunction<T, U, R> implements
       ^
where T,U,R are type-variables:
  T extends Object declared in class GenericFunction
  U extends Object declared in class GenericFunction
  R extends Object declared in class GenericFunction

1 error

我该怎么做?

2 个答案:

答案 0 :(得分:8)

我不知道为什么你会想要这样的东西,但这似乎是一个有趣的挑战......

主要问题是功能和功能BiFunction实现默认的andThen函数,两者都具有完全相同的签名,因此您的类不知道要调用哪个。你只需要提供自己的实现,然后它就不再含糊了。然而,实施是棘手的。

java docs说方法:

  

返回一个首先将此函数应用于其输入的组合函数,然后将after函数应用于结果。

...这意味着返回一个新的GenericFunction,其中两个apply方法现在都是合成。

我给你这个怪物:

public class GenericFunction<T, U, R> implements Function<T, R>, BiFunction<T, U, R> {

    @Override
    public R apply(T t, U u) {
        return null;
    }

    @Override
    public R apply(T t) {
        return null;
    }

    @Override
    public <V> GenericFunction<T, U, V>  andThen(Function<? super R, ? extends V> after) {
        return new GenericFunctionAndThen<>(after);
    }

    private class GenericFunctionAndThen<V> extends GenericFunction<T, U, V> {
        private final Function<? super R, ? extends V> after;

        public GenericFunctionAndThen(Function<? super R, ? extends V> after) {
            this.after = after;
        }

        @Override
        public V apply(T t) {
            return after.apply(GenericFunction.this.apply(t));
        }

        @Override
        public V apply(T t, U u) {
            return after.apply(GenericFunction.this.apply(t, u));
        }
    }
}

这使用了我所知道的Java最晦涩的功能......我甚至不知道这个名字!如果方法为shadowed,则ClassName.this在嵌套类中用于引用封闭实例中的方法(或字段)。

答案 1 :(得分:6)

@romacafe's answer扩展,我不喜欢的一件事是GenericFunctionAndThen扩展GenericFunction而不重用其超级类的任何行为 - 这看起来像我难闻的气味。

如果您将GenericFunction作为接口实现,那么事情会更清晰:

public interface GenericFunction<T, U, R> extends Function<T, R>, BiFunction<T, U, R> {
    @Override
    default <V> GenericFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
        return new GenericFunction<T, U, V>() {
            @Override
            public V apply(final T t, final U u) {
                return after.apply(GenericFunction.this.apply(t, u));
            }

            @Override
            public V apply(final T t) {
                return after.apply(GenericFunction.this.apply(t));
            }
        };
    }
}

通过这种方式,您可以简单地实现泛型行为(andThen方法),并且可以在不依赖继承的情况下在特定类中实现特定行为(2 apply方法)。