用特定的覆盖通用可变参数函数

Overriding generic varargs function with a specific one

我正在尝试编写一个在其实现中使用另一个权重函数 (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;
    }

有没有更优雅的方法来做到这一点?这被认为是好的形式吗?

您可能喜欢使用泛型?

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;
    }
}

您也可以只使用一个参数并允许调用者将他的所有参数包装在一个 class 中。如果您有多种不同类型的参数,这可能会更好。

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;
    }
}

泛型是必经之路。但是在你的问题中解释这个:

However, because I don't know what parameters such function would require, I defined it like this:

和您对 的第一条评论我认为您的问题是您只需要(并且应该)声明每个采用不同数量参数的方法。没有别的办法,但无论如何,这样更清楚。

所以你应该有这样的东西:

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);

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

以及您问题的答案:

Is this considered good form?

IMO 制作接受 Object 数组的函数,然后实现一种方法,根据需要解释参数并执行所需的操作,这绝不是一个好习惯。我认为它强烈反对整个接口的想法。

声明“告诉”它们在做什么的方法,然后在需要时添加新的方法声明或重构您的接口和已经实现的方法总是一个更好的主意。

如果您选择在任何需要一些灵活性的时候传递“对象列表”,您很快就会成为其中的 knee-deep。

现在这可能会提出一个问题,我是否必须实现此接口中的所有方法?是的,但如果您不想,您可以定义单独的接口并让您的 class 实现其中的 1 个或多个 or/and 使用 extends 来制作接口层次结构。