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

私はこれをやろうとして戦ってきましたが、失敗しました。

私がこれを実行できるようにしたい理由の1つは、将来、次のように記述できるようにすることでもあります。

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

ただし、完全には機能しません。タイプ、、SおよびValidationDataP実行p1および<S, ValidationData>実行p2<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 に答える