使用其通用参数扩展接口的方法签名实现接口

Implement an interface with a method signature whose generic parameters extend an interface

下面是我正在尝试完成的示例。我正在尝试创建实现 GenericRunnerLibraryRunner。但是,我收到 IDE 警告,指出 LibraryRunner 未实现 GenericRunner 接口中的方法。这是有道理的,方法签名不匹配,但是如何在仍然使用扩展 GenericCalculatorLibraryCalculator 的同时使方法签名匹配?

public class LibraryRunner implements GenericRunner {
    @Override
    public <T> T run(LibraryCalculator<T> calculator) {
        return T;
    }
}

public interface GenericRunner {
    <T, A> T run(GenericCalculator<T, A> calculator);
}


public interface LibraryCalculator<T> extends GenericCalculator<T, LibraryAlgorithm> {
    T calc(LibraryAlgorithm algorithm) throws LibraryException;
}

public interface GenericCalculator<T, A> {
    T calc(A algorithm) throws Exception;
}


public class LibraryException extends Exception {
    
}

当您重写或实现一个方法时,您始终需要满足被重写方法的条件,例如您仍然应该能够调用带有参数 GenericCalculator 的 LibraryRunner.run。否则这样写是没有意义的:

LibraryRunner libRunner = new LibraryRunner();
GenericRunner genRunner = libRunner;
genRunner.run(new GenericCalculator<>());

覆盖异常确实有效,因为当您调用 GenericCalculator.calc 时您期望任何异常并调用 LibraryCalculator.calc 将其缩小到仅 LibraryException.

您可以查看覆盖方法作为承诺的更多信息。

接口的定义方式,即使 LibraryCalculatorGenericCalculator 的子类型,您也无法覆盖该方法并更改其签名。另一个答案解释了原因。

解决这个问题的一种方法是用计算器类型参数化 GenericRunner 接口:

public interface GenericRunner<T, A, C extends GenericCalculator<T, A>> {
    T run(C calculator);
}

public class LibraryRunner<T> implements GenericRunner<T, LibraryAlgorithm, LibraryCalculator<T>> {

    @Override
    public T run(LibraryCalculator<T> calculator) {
        ...
    }

}

但请注意,您不能在 LibraryRunner 方法中 return 一个 Object,因为它不匹配 T。如果你想 return 像 Object 这样的特定类型(这违背了通用 LibraryCalculator 的目的),你必须明确指定它:

public class LibraryRunner implements GenericRunner<Object, LibraryAlgorithm, LibraryCalculator<Object>> {

    @Override
    public Object run(LibraryCalculator<Object> calculator) {
        return new Object();
    }

}

如果这不是您想要的,则由 LibraryRunner 的用户决定 T 应该绑定到哪种类型。