6

これは基本的なJavaの質問のようです。

Pipelineメソッドを持つインターフェースが1つありますexecute(Stage)

次に、から拡張するサブインターフェイスを作成します。PipelineたとえばBookPipeline、メソッドが好きexecute(BookStage)です。

BookStageから拡張しStageます。

この種の定義はjavaコンパイルを渡すことができなかったようです。

それについて何か提案はありますか?

4

3 に答える 3

8

ジェネリックの使用を検討することをお勧めします。

public interface Pipeline<T extends Stage> {
     public void execute(T stage);
}

public interface BookPipeline extends Pipeline<BookStage> {
     @Override
     public void execute(BookStage stage);
}
于 2012-05-04T16:12:26.593 に答える
4

@Jeffreyが可能な解決策として書いたことに加えて、なぜそれができないのかを理解することが重要です。

Pipelineメソッドとのインターフェースがexecute(Stage)あり、 との拡張インターフェースがあるBookPipelineとしexecute(BookStage)ます。

Concまた、 を実装するクラスがあるとしますBookPipeline

次のことを考慮してください

Pipeline p = new Conc();
p.execute(new Stage());

何が起こるか?それは危険です!
Java はそれを避けたいので、そもそもこの状況を防ぎたいのです。

ルールは、クラス/インターフェースを拡張することで動作を追加できますが、それを減らすことはできません

于 2012-05-04T16:16:05.873 に答える
2

@amit の答えを詳しく説明すると、Conc.executeメソッドが aBookStageをパラメーターとして受け取り、その代わりに a をスクイーズしようとするため、コード スニペットは安全Stageではありません (もちろん、すべてStageの s がBookStages であるとは限りません)。

ただし、別の方法、つまり のパラメータ型を のようなBookePipeline.executeスーパータイプにしたいと考えているとします。StageObject

明確にするために、次のようになります。

interface Pipeline
{
  void execute(Stage s);
}

interface BookPipeline extends Pipeline
{
  @Override
  void execute(Object s);
}

そして、Conc実装する場所BookPipeline

Pipeline p = new Conc();
p.execute(new Stage());

Liskov Substitutability に違反していないため、これは理論的には安全です。パラメータ以上を取るStage実装には a を安全に渡すことができます。Stageこれは反変性として知られています。Java は反変の引数の型をサポートしていませんが、サポートしている言語があります。

あなたの元の質問は、指定された理由で安全ではない共変の引数の型に関連しています (しかし、奇妙なことに、 Eiffelと呼ばれる言語ではこれが許可されています)。

ただし、Java は共変の戻り値の型をサポートしています。想像しPipelineてみてください

Stage getAStage();

BookPipelineこのメソッドを次のようにオーバーライドすることは完全に合法です 。

@Override
BookStage getAStage();

次に、次のようになったと想像してください。

public void someMethodSomewhere(Pipeline p)
{
  Stage s = p.getAStage();
  //do some dance on Stage
}

で定義されているのとまったく同じようにDonc実装Pipelineおよびオーバーライドするクラスがあると仮定すると(したがって、まだ を返します)、これらの呼び出しは両方とも問題ありません。getAStage()PipelineStage

someMethodSomewhere(new Conc());
someMethodSomewhere(new Donc());

type の変数にはいつStageでも a 以下 (例: ) を入れることができるからです。BookStageStage

したがって、ルールをメソッドのオーバーライドに特に関連するように言い換えると、メソッドをオーバーライドする拡張クラス/インターフェースは、それらのメソッドが受け入れるものをより一般化し、それらが返すものをより具体的にするだけです。(ただし、Java の場合は、より具体的な戻り値の型のみが許可されます。)

覚えておいてください、PECS - Producer Extends、Consumer Super (Joshua Bloch、Effective Java)

于 2015-01-06T15:38:53.290 に答える