我正在编写一份关于优化的C++库,但我遇到了一个有趣的逆变类型问题。
因此,我定义了一个"函数"层次结构,基于它们能计算的信息。
但是,为了创建相应的优化器类,我们必须使HessianOptimizer扩展ThirdOrderOptimizer。但是,库用户必须修改库才能这样做!因此,虽然我们可以添加ThriceDifferentiableFunction而不必修改库,但逆变类型似乎失去了这个属性。这似乎只是一个因素,类声明其父类型而不是子类型而导致的。那么,你应该如何处理呢?有没有什么好的方法呢?
因此,我定义了一个"函数"层次结构,基于它们能计算的信息。
class Function {
public:
double value()=0;
}
class DifferentiableFunction : public Function {
public:
const double* gradient()=0;
}
class TwiceDifferentiableFunction : public DifferentiableFunction {
public:
const double* hessian()=0;
}
这都很好,但现在我希望针对优化器定义接口。例如,某些优化器需要梯度信息或海森矩阵信息才能进行优化,而有些则不需要。因此,优化器的类型与函数的类型是逆变的。
class HessianOptimizer {
public:
set_function(TwiceDifferentiableFunction* f)=0;
}
class GradientOptimizer : public HessianOptimizer {
public:
set_function(DifferentiableFunction* f)=0;
}
class Optimizer: public GradientOptimizer {
public:
set_function(TwiceDifferentiableFunction* f)=0;
}
从类型理论的角度来看,这似乎是有道理的,但奇怪的是,通常当人们想要扩展代码时,他们会继承已经存在的类。例如,如果其他人正在使用此库,并且他们想要创建一种需要比海森矩阵更多信息的新型优化器,他们可能会创建一个类似于:
class ThriceDifferentiableFunction: public TwiceDifferentiableFunction }
public:
const double* thirdderivative()=0;
}
但是,为了创建相应的优化器类,我们必须使HessianOptimizer扩展ThirdOrderOptimizer。但是,库用户必须修改库才能这样做!因此,虽然我们可以添加ThriceDifferentiableFunction而不必修改库,但逆变类型似乎失去了这个属性。这似乎只是一个因素,类声明其父类型而不是子类型而导致的。那么,你应该如何处理呢?有没有什么好的方法呢?