避免在通用工厂中投射

Avoid cast in generic factories

假设我有一个如下所示的 class 结构:

public abstract class Interval<I extends Interval<?>> {
    public static final IntervalFactory<? extends Interval<?>> factory = null;

    // some variables and methods
}

public class Week extends Interval<Week> {
    public static final IntervalFactory<Week> factory = new WeekFactory();
    
    // some variables and methods
}

public interface IntervalFactory<I extends Interval> {
    I containing(LocalDate date);
    List<I> containing(LocalDate startDate, LocalDate endDate);
}

public class WeekFactory implements IntervalFactory<Week> {
    @Override
    public Week containing(LocalDate date) {
        // implementation
    }

    @Override
    public List<Week> containing(LocalDate startDate, LocalDate endDate) {
        // implementation
    }
}

现在我有一个使用这些间隔和工厂的 class:

public class SomeClass<I extends Interval<?>> {
    private final IntervalFactory<I> intervalFactory;

    public DistributorForSlowQuantifier() {
        this.intervalFactory = (IntervalFactory<I>) I.factory;
    }
    
    public Map<I, Double> distribute(double value) {
        // implementation
    }
}

如果 class 需要从类型变量创建实例,这是解决问题的正确方法吗?

SomeClass 构造函数中是否有绕过转换的方法?

显而易见的事情是行不通的——在 SomeClass 中使用通配符作为 intervalFactory 的类型参数会丢失所有类型信息,工厂是静态的,所以我不能将 I 用作类型参数,如果我不将它们标记为静态,我需要一个 I 的实例来访问工厂...

强制转换是绝对安全的,只要Interval实现选择“对应”的工厂即可,但感觉还是……不对。

SomeClass 构造函数中的转换甚至不起作用。它将始终使用 Interval.factory,无论它是否对应于您想要的工厂类型。 I.factory并没有按照你的想法去做。

迄今为止最常见和最明智的方法:将适当的工厂传递给构造函数。您可以使用静态导入和静态工厂方法为此添加一些语法糖,使其看起来像例如new DistributorForSlowQuantifier(days()) 之类的。还有其他更复杂和混乱的解决方法,但考虑到所有因素,它们更糟糕。