使用泛型链接任务

时间:2011-03-24 08:35:27

标签: java generics

我正在尝试为链接任务创建一个API。

首先,我设计了一个定义任务的非常简单的界面:

public interface Task<U, V> {  
    U execute(V input);  
}

其中V是输入类型,U是任务的输出类型。

我要创建的是Chain类,它会链接Tasks列表。

例如,我想执行:Task1<TypeA, TypeB> -> Task2<TypeB, TypeC> -> Task3<TypeC, TypeD>

这个Chain类因此是Task<TypeA, TypeD>

所以我写了这段不编译的代码:

public class Chain<U, V> implements Task<U, V> {  
    List<Task<?, ?>> taskList;

    public Chain() {  
        taskList = new LinkedList<Task<?, ?>>();  
    }

    @Override  
    public U execute(V input) {  
        V currentInput = input;  
        U output = null;  
        for (Task<?, ?> task : taskList) {  
            output = task.execute(currentInput);
            // Compile error because currentInput is of type V
            // and output of type U  
            currentInput = output; // Compile error as well  
        }  
        return output;  
    }

    // Other methods to add and remove tasks in the list  
}

我明白为什么它无法编译,但我不知道如何实现有效的方法并解决我的问题。

有没有人遇到过这种问题?

亲切的问候,

3 个答案:

答案 0 :(得分:5)

您的Task课程与Guava课程Function几乎相同。您可以使用它而不是定义自己的那个。

使用Function的一个好处是你可以使用Functions类中的辅助方法,其中一个方法是compose()

Function<String,MyObject1> stringToMyObject1 = ...;
Function<MyObject1, AnotherObject> myObject1ToAnotherObject = ...;
Function<String,AnotherObject> stringtoAnotherObject = Functions.compose(myObject1ToAnotherObject, stringToMyObject1);

通过重复调用compose()可以实现更深层次的链接。

即使您出于某种原因不想使用Guava,也可以从这种方法中获取灵感:使用已知类型参数链接任意两个函数/任务会创建一个具有易于计算的类型参数的新函数/任务。

答案 1 :(得分:4)

不是试图在(非通用)列表中维护任务,而是可以尝试“装饰器”方法(缺少更好的单词),即定义一个将另一个任务作为参数的类,执行一些任务然后通过其结果是另一项任务。或者作为一个复合,它接受两个任务,并将第一个的输出作为输入传递给第二个。

答案 2 :(得分:0)

尝试以下方法。你遇到的问题是你的输出不能同时是V和U.

public U execute(V input) {
    Object object = input;
    for (Task task : taskList) 
        object = task.execute(object);
    return (U) object;
}