Java:解决有界类型参数下接口多态的继承编译冲突
首先贴出原代码结构:
class Declarations { interface Function<I, O> { interface BinaryFunction<I> extends Function<I, Boolean> {} } static abstract class FunctionImpl<I, O> implements Function<I, O> { static class BinaryFunctionImpl<I> extends FunctionImpl<I, Boolean> implements Function.BinaryFunction<I> {} } interface Optimizer<I, O, F extends Function<I, O>> { interface BinaryOptimizer<I> extends Optimizer<I, Boolean, Function.BinaryFunction<I>> {} } static abstract class AbstractOptimizer<I, O, F extends Function<I, O>> implements Optimizer<I, O, F> {} static abstract class OptimizerImpl<I, O, F extends FunctionImpl<I, O>> extends AbstractOptimizer<I, O, F> { static class BinaryOptimizerImpl<I> extends OptimizerImpl<I, Boolean, FunctionImpl.BinaryFunctionImpl<I>> implements BinaryOptimizer<I> {} } }
编译器报错信息:
'Optimizer' cannot be inherited with different type arguments: 'BinaryFunctionImpl' and 'BinaryFunction'
问题根源
Java泛型是不变的——即使BinaryFunctionImpl<I>实现了BinaryFunction<I>,Optimizer<I, Boolean, BinaryFunctionImpl<I>>和Optimizer<I, Boolean, BinaryFunction<I>>仍被视为完全独立的参数化类型,无法同时作为同一个类的超类型。OptimizerImpl的泛型边界限制F必须是FunctionImpl子类,而BinaryOptimizer<I>要求F是BinaryFunction<I>接口,二者的约束无法直接兼容。
最小改动解决方案
步骤1:调整OptimizerImpl的泛型边界
将OptimizerImpl的泛型参数约束从F extends FunctionImpl<I, O>放宽为F extends Function<I, O>,使其能接受所有Function的实现类(包括接口):
static abstract class OptimizerImpl<I, O, F extends Function<I, O>> extends AbstractOptimizer<I, O, F> { // 若原有代码依赖FunctionImpl的特定方法,可通过强制转换兼容: protected FunctionImpl<I, O> asFunctionImpl(F function) { return (FunctionImpl<I, O>) function; } }
步骤2:修正BinaryOptimizerImpl的泛型参数
让BinaryOptimizerImpl继承OptimizerImpl时,直接使用BinaryFunction<I>作为泛型参数,与BinaryOptimizer<I>的接口定义保持一致:
static class BinaryOptimizerImpl<I> extends OptimizerImpl<I, Boolean, Function.BinaryFunction<I>> implements Optimizer.BinaryOptimizer<I> {}
关于仅修改BinaryOptimizerImpl的可行性
答案是否定的。冲突的核心在于OptimizerImpl的泛型边界限制了F的类型范围,仅修改子类声明无法调和FunctionImpl子类与BinaryFunction接口之间的约束矛盾,必须放宽OptimizerImpl的泛型限制才能解决问题。
内容的提问来源于stack exchange,提问作者programonkey

