用特定的varargs函数重写泛型varargs功能



我正试图编写一个库函数(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);

如果更有可能只有两个Ts。

你的问题的答案是:

这被认为是好形式吗?

IMO生成采用Objects数组的函数,然后实现一个按其意愿解释params并按其意愿执行的方法,这从来都不是一个好习惯。我认为这强烈反对接口的整个概念。

声明方法总是一个更好的想法;告诉";然后添加一个新的方法声明,或者在需要的时候重构你的接口和已经实现的方法。

如果您选择通过";对象列表";任何时候你需要一些灵活性,你很快就会陷入困境。

现在这可能会提出一个问题,我必须实现这个接口上的所有方法吗?是的,但如果您不想这样做,您可以定义单独的接口并使您的类实现其中的一个或多个,或者/并使用extends来创建接口层次结构。

相关内容

  • 没有找到相关文章

最新更新