0

是的,泛型是一个反复出现的主题,这里又来了……

目前,我有这个代码。Processor是一个“简单”的通用接口。

public final class ProcessorChain<IN extends MessageProvider, OUT extends MessageProvider>
    implements Processor<IN, OUT>
{
    /**
     * The resulting processor
     */
    private final Processor<IN, OUT> p;

    /**
     * Start a processing chain with a single processor
     *
     * @param p the processor
     * @param <X> the input type
     * @param <Y> the output type
     * @return a single element processing chain
     */
    public static <X extends MessageProvider, Y extends MessageProvider>
        ProcessorChain<X, Y> startWith(final Processor<X, Y> p)
    {
        return new ProcessorChain<X, Y>(p);
    }

    /**
     * Private constructor
     *
     * @param p the processor
     */
    private ProcessorChain(final Processor<IN, OUT> p)
    {
        this.p = p;
    }

    /**
     * Add an existing processor to that chain
     *
     * <p>Note that this returns a <b>new</b> chain.</p>
     *
     * @param p2 the processor to add
     * @param <NEWOUT> the return type for that new processor
     * @return a new chain consisting of the previous chain with the new
     * processor appended
     */
    public <NEWOUT extends MessageProvider> ProcessorChain<IN, NEWOUT>
        chainWith(final Processor<OUT, NEWOUT> p2)
    {
        return new ProcessorChain<IN, NEWOUT>(merge(p, p2));
    }

    public Processor<IN, OUT> end()
    {
        return this;
    }

    @Override
    public OUT process(final ProcessingReport report, final IN input)
        throws ProcessingException
    {
        return p.process(report, input);
    }

    /**
     * Merge two processors
     *
     * @param p1 the first processor
     * @param p2 the second processor
     * @param <X> the input type of {@code p1}
     * @param <Y> the output type of {@code p1} and input type of {@code p2}
     * @param <Z> the output type of {@code p2}
     * @return a processor resulting of applying {@code p2} to the output of
     * {@code p1}
     */
    private static <X extends MessageProvider, Y extends MessageProvider, Z extends MessageProvider>
        Processor<X, Z> merge(final Processor<X, Y> p1, final Processor<Y, Z> p2)
    {
        return new Processor<X, Z>()
        {
            @Override
            public Z process(final ProcessingReport report, final X input)
                throws ProcessingException
            {
                return p2.process(report, p1.process(report, input));
            }
        };
    }
}

所以,目前,我可以写:

// p1 does <X, Y>, p2 does <Y, Z>, p3 does <Z, T>
Processor<X, T> p = ProcessingChain.startWith(p1).chainWith(p2).chainWith(p3).end();

它有效。事实上,我对泛型的研究从未如此深入。

我希望能够写的是:

Processor<X, T> p = ProcessingChain.start().add(p1).add(p2).add(p3).end();

我一直在努力尝试做到这一点,但失败了。

我希望能够做到这一点的一个原因也是,在未来,能够写:

Processor<X, T> p = ProcessingChain.start().add(p1).stopOnError().etc().etc()

而且我觉得如果我知道怎么做.start(),那么“实用”处理器就不会成为问题。

那么,该怎么做呢?

4

3 回答 3

2

裸启动方法无法推断生成的 ProcessorChain 必须是的类型。此外,正如@PaulBellora 指出的那样,您所勾画的 start() 方法本身不能是处理器,因为它没有足够的信息。

您可以使用一个单独的类作为 start() 方法的结果,尽管它不能是无参数的。例如:

public class ProcessorChainFactory<M extends MessageProvider> {

    public static <X extends MessageProvider> ProcessorChainFactory<X> start() {
        return null;
    }

    public static <X extends MessageProvider> ProcessorChainFactory<X> start(Class<X> clazz) {
        return null;
    }

    public <X extends MessageProvider> ProcessorChain<M, X> add(Processor<M, X> processor) {
        // TODO Auto-generated method stub
        return null;
    }        
}

然后可以通过几种方式调用它:

    Processor<MessageProvider1, Final> processor = ...;

    ProcessorChain<MessageProvider1, Final> processor1 = ProcessorChainFactory.<MessageProvider1> start().add(processor);
    ProcessorChain<MessageProvider1, Final> processor2 = ProcessorChainFactory.start(MessageProvider1.class).add(processor);

我的感觉是,这不会让你比你的当前更进一步ProcessingChain.startWith(p1),但也许它会有所帮助。

于 2013-01-31T01:18:30.983 回答
1

无参数start方法应该返回什么?这是问题的症结所在,尽管您只是在问题中提到了它。

请注意,您已声明ProcessorChain为实现Processor- 因此任何实例都ProcessorChain必须像一个实例一样。出于这个原因,创建一个没有包装的ProcessorChain实例是没有意义的。Processor

一般来说,我会说构建器不应该实现它所构建的接口,但是在写完之后我认为我至少会对看到相反的论点感兴趣。

于 2013-01-31T01:06:50.333 回答
1

好吧,好吧,有一种方法虽然有点骇人听闻:

public static <X extends MessageProvider> ProcessorChain<X, X> start()
{
    final Processor<X, X> p = new Processor<X, X>()
    {
        @Override
        public X process(final ProcessingReport report, final X input)
            throws ProcessingException
        {
            return input;
        }
    };

    return new ProcessorChain<X, X>(p);
}

但是,它不会完全起作用。使用 types SValidationDataand Pp1doing<S, ValidationData>p2doing <ValidationData, P>,写作:

ProcessorChain.start().chainWith(p1).chainWith(p2).end()

导致此编译错误:

<NEWOUT>chainWith(Processor<MessageProvider,NEWOUT>) 
in ProcessorChain<MessageProvider,MessageProvider>
cannot be applied to
(Processor<S,ValidationData>)

上面的代码是我的第一次尝试......

但如果我写:

ProcessorChain.<S>start().chainWith(p1).chainWith(p2).end()

那么它的工作原理!

于 2013-01-31T01:15:24.773 回答