3

このトピックにはいくつかのスレッドがあることは知っていますが、問題がどこにあるのか理解できませんでした。検索結果を上下に読むと、これまで以上に戸惑います。問題を明確にできるといいのですが。

メッセージタイプ階層があり、これらのメッセージの汎用プロセッサ階層があります。これは私がこれまで実行してきました。ここで、プロセッサのファクトリメソッドを実装し、選択した一般的なアプローチに固執したいと思います。私の例を見てください:

abstract class Message
{
    abstract int getTest();
}

class MyMessage1 extends Message
{
    @Override
    int getTest()
    {
        return 1;
    }
}

class MyMessage2 extends Message
{
    @Override
    int getTest()
    {
        return 2;
    }
}

interface Processor<T extends Message>
{
    void initialize(final T p_message);

    void doWork();
}

abstract class BaseMessageProcessor<T extends Message> implements Processor<T>
{
    private T message;

    @Override
    public void initialize(T p_message)
    {
        message = p_message;
    }

    protected T getMessage()
    {
        return message;
    }
}

class MyMessage1Processor extends BaseMessageProcessor<MyMessage1>
{
    @Override
    public void doWork()
    {
        // perfectly valid assignment
        MyMessage1 msg = getMessage();
        // do something
    }
}

class MyMessage2Processor extends BaseMessageProcessor<MyMessage2>
{
    @Override
    public void doWork()
    {
        // perfectly valid assignment
        MyMessage2 msg = getMessage();
        // do something
    }
}

これまでのところ、これは有効であり、期待どおりに機能しています。しかし今、工場がやってくる:

class ProcessorFactory
{
    <T extends Message> Processor<T> createProcessor(final Class<T> p_msgType)
    {
        if (p_msgType.equals(MyMessage1.class))
        {
            // Type mismatch: cannot convert from MyMessage1Processor to Processor<T>
            return new MyMessage1Processor();
        }
        else if (p_msgType.equals(MyMessage2.class))
        {
            // Type mismatch: cannot convert from MyMessage2Processor to Processor<T>
            return new MyMessage2Processor();
        }
        else
        {
            throw new Exception("Unsupported message type: " + p_msgType);
        }
    }
}

多分それは私がここで作っている愚かな失敗ですが、私はそれを見ることができません。誰かが私にヒントを与えることができれば、私は感謝するでしょう。

よろしく

セバスチャン

編集:OK私のせい。問題は、「デフォルトのロケール」としてコメントとして記述されたコンパイラエラーが発生することです(たとえば、2番目のreturnステートメントの場合はコンパイルエラーが発生します)。

タイプの不一致:MyMessage2ProcessorからProcessorに変換できません

4

1 に答える 1

2

失敗する理由を理解するには、型消去がどのように機能するかを理解する必要があります。

あなたは自分が正しいことをしていることをはっきりと知っていますが、情報がキャンセルされているため、コンパイラはそれを知らず、そして最も重要なことに、設計のためにそれを知ることができません

この概念をさらに説明してみましょう。型消去のため、型Tはコンパイル時にjava.lang.Objectに変換され、Javaコンパイラのコンパイル時情報はありません。

その場合はタイプになりa.getClass().equals(MyClass.class)ますa.getClass()MyClass<MyClass>


重要:ひどいデザインにつながる可能性があるため、このコードをできるだけ記述しないでください。バグや保守不可能なコードの地獄で死にたくない場合は、型安全言語に型安全の論理的証拠を使用させたり、型証拠をコンパイルしたりしないでください。コンパイラでキャストによって型安全性を強制すると、ある日クラス構造を変更し、ファクトリを変更するのを忘れると、すべてが正常にコンパイルされますが、実行時にBOOMが発生するリスクがあります。

ファクトリメソッドは一般に、オブジェクトを生成するロジックを呼び出し元から隠すためのパターンであり、そのような状況に陥った場合は、ジェネリックを正しく使用していないことを意味している可能性があります。もう1つのクラスを作成し、すっきりとしたデザインにすることをお勧めします。

たぶん、あなたは追加の質問を追加することができます:タイプセーフな方法でこのパターンを実装する方法は?

于 2012-07-18T07:23:59.337 に答える