我正试图编写一个库函数(f(,它在实现中使用另一个权重函数(w(。我希望使用默认的权重函数(dw(,但也允许库函数(f(的用户提供他们自己的权重函数。
我为权重函数做了一个接口,它有一个计算函数。然而,因为我不知道这样的函数需要什么参数,所以我这样定义它:
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;
}
有更优雅的方法吗?这被认为是好形式吗?
您可能想要使用泛型?
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;
}
}
Generics是最好的选择。但在你的问题中解释一下:
然而,因为我不知道这样的函数需要什么参数,我这样定义它:
以及Gregor Koukoullis对您的第一个回答,我认为您的问题是,您只需要(并且应该(声明每一个使用不同数量参数的方法。没有其他办法了,但无论如何,这种方式更清楚。
所以你应该有这样的东西:
public interface WeightFunction<T> {
double calculate(T... arguments);
double calculate(Long seed, T... arguments);
double calculate(Long seed, Integer somethingElse, T... arguments);
}
为什么变量参数必须是最后一个?看看这个。公认的答案显然不是最明确的,但很少有其他人会澄清这个问题。
现在,当您在示例中实现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
s。
你的问题的答案是:
这被认为是好形式吗?
IMO生成采用Object
s数组的函数,然后实现一个按其意愿解释params并按其意愿执行的方法,这从来都不是一个好习惯。我认为这强烈反对接口的整个概念。
声明方法总是一个更好的想法;告诉";然后添加一个新的方法声明,或者在需要的时候重构你的接口和已经实现的方法。
如果您选择通过";对象列表";任何时候你需要一些灵活性,你很快就会陷入困境。
现在这可能会提出一个问题,我必须实现这个接口上的所有方法吗?是的,但如果您不想这样做,您可以定义单独的接口并使您的类实现其中的一个或多个,或者/并使用extends
来创建接口层次结构。