はい、ジェネリックは再発する主題です、そしてここでそれは再び行きます...
現在、私はこのコードを持っています。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();
私はこれをやろうとして戦ってきましたが、失敗しました。
私がこれを実行できるようにしたい理由の1つは、将来、次のように記述できるようにすることでもあります。
Processor<X, T> p = ProcessingChain.start().add(p1).stopOnError().etc().etc()
.start()
そして、その方法を知っていれば、途中の「ユーティリティ」プロセッサは問題にならないだろうと感じています。
それで、それはどのように行うのですか?