我正在尝试编写一个在实现中使用另一个权重函数(w)的库函数(f)。 我想使用默认的权重函数(dw),但也要允许库函数(f)的用户提供自己的权重函数(w)。
我为重量函数创建了一个具有计算功能的接口。但是,由于我不知道该功能需要什么参数,因此我这样定义它:
public interface WeightFunction {
double calculate(Object ... arguments);
}
但是,当我使用默认函数(dw)覆盖它时,我做了一件丑陋的事情:
@Override
public double calculate(Object ... arguments) {
return calculate((Pixel)arguments[0], (Pixel)arguments[1]);
}
public double calculate(Pixel u, Pixel v){
//logic here
return 0;
}
是否有更优雅的方法来做到这一点?这是好表格吗?
答案 0 :(得分:2)
您可能想使用泛型?
public interface WeightFunction<T> {
double calculate(T ... arguments);
}
class A implements WeightFunction<Pixel> {
@Override
public double calculate(Pixel... arguments) {
return calculate(arguments[0], arguments[1]);
}
public double calculate(Pixel u, Pixel v){
//logic here
return 0;
}
}
您还可以只使用一个参数,并允许调用方将其所有参数包装在一个类中。如果您有多个不同类型的参数,这可能会更好。
public interface WeightFunction<T> {
double calculate(T argument);
}
@Override
public double calculate(SeededPixels arg) {
return calculate(arg.u, arg.v); // * arg.seed
}
class SeededPixels {
public final Pixel u;
public final Pixel v;
public final long seed;
SeededPixels(Pixel u, Pixel v, long seed) {
this.u = u;
this.v = v;
this.seed = seed;
}
}
答案 1 :(得分:1)
使用泛型是必经之路。但是在您的问题中解释一下:
但是,因为我不知道该函数需要什么参数,所以我这样定义它:
以及您对answer from Gregor Koukkoullis的第一条评论,我认为您的问题是您只需要(并且应该)声明每个采用不同数量参数的方法。只是没有别的办法了,但是这种方式还是很清楚的。
所以你应该有这样的东西:
public interface WeightFunction<T> {
double calculate(T... arguments);
double calculate(Long seed, T... arguments);
double calculate(Long seed, Integer somethingElse, T... arguments);
}
为什么varags参数必须是最后一个? See this。公认的答案可能不是最清晰的答案,但很少有人会澄清这个问题。
现在,当您在示例中实现calculate
时,便以某种方式知道参数是什么?
@Override
public double calculate(Object ... arguments) {
// you know here that the 2 first are pixels, dont you?
return calculate((Pixel)arguments[0], (Pixel)arguments[1]);
}
因此,只要您具有相同的知识,就可以在界面中创建所需属性的声明。甚至:
double calculate(Long seed, T t1, T t2);
如果更可能只有两个T
。
问题的答案:
这被认为是很好的形式吗?
IMO,创建带有Object
数组的函数,然后实现一种可按需解释参数并执行所需功能的方法从来都不是一个好习惯。我认为这强烈反对整个界面的想法。
始终声明一个“告诉”它们在做什么的方法,然后在需要时添加一个新的方法声明或重构您的接口和已经实现的方法,总是一个更好的主意。
如果您选择在需要灵活性时随时传递“对象列表”,那么您很快就会陷入困境。
现在这可能会引起一个问题,我必须在该接口中实现所有方法吗?是的,但是如果您不想这样做,则可以定义单独的接口并让您的类实现1个或多个接口,或者/并且使用extends
来构成接口层次结构。