0

派生クラス Action、Comedy、Drama を持つクラス Movies があります。私は、rentedMovies と呼ばれるさまざまな映画の配列を持っています。

単純な for ループを使用して配列をループすると、

for(int i = 0; i < rentedMovies.lenght; i++){
  ..Do something..
}

IntelliJ IDE は、このループを foreach に変更できることを示唆しています。

for(Movie movie: rentedMovies){
 ..Do something..
}

しかし、これはすべての映画要素が派生クラスではなく Movie クラスのオブジェクトとして扱われることを意味するのではないでしょうか? それはIDEによる間違った提案ですか、それとも私は正しく考えていませんか? ありがとう。

4

4 に答える 4

2

この仮定は、rendedMovies が次のように宣言されているという事実によって既に暗示されています。

ArrayList<Movie> rentedMovies

そのため、コレクション内に含まれるオブジェクトについて知ることができる最も具体的な情報は、それらが型であるということですMovie。ジェネリック コレクションは特定の型だけを持つことができるため、Java ではこれを行う必要があります。すべてのサブクラスをコレクションに追加できるようにするには、共通のスーパー クラスを提供する必要があります。

オブジェクトをクラスに追加すると、型情報は失われます。例えば:

Comedy comedy = new Comedy();
rentedMovies.add(comedy);
Comedy comedy2 = rentedMovies.get(0); // compile error: get returns Movie
Movie movie = rentedMovie.get(0); // correct

つまり、現在の映画のインデックスが必要ない場合、スニペットは同等です。for-each ステートメントは内部でイテレータを操作することに注意してください。そのため、ループ内でコレクションを変更する場合は、自分が行っていることに注意する必要があります

コレクションから一度取得した要素の特定の情報を取得したい場合は、自分でそれをダウンキャストする必要があります (そして、ハンド チェックなしで型の安全性をコンパイルすることを忘れてください)。

public Comedy asComedy() {
  return this instanceof Comedy ? (Comedy)this : null;
}

ただし、それを行う必要がある場合は、継承を再設計する必要があります。動作を完全に のサブクラス内に移動Movieして、特定の型を知る必要がなく、共通インターフェイスのメソッドを呼び出すだけでよいかもしれません。

于 2013-10-10T04:12:28.670 に答える
1

とにかくrentedMoviesとして宣言されていると思いMovies[]ますので、元の for ループはそれらを Movie オブジェクトとして保持します。

サブクラスの特定のメソッドを使用したい場合は、どちらの場合もキャストする必要があります。

の実装を使用する利点は、(int i = 0; i < rentedMovies.lenght; i++)配列全体をループする必要がない場合 (Intellij はこの警告を表示しません)、または現在のオブジェクトに対するインデックス位置を使用する必要がない場合、インデックスがあることです。

于 2013-10-10T04:11:42.067 に答える
1

異なる型の配列がある場合、Array 変数の型はスーパークラスである必要があります。

とにかく、ループ内で特定のタイプのムービーを検索する場合は、明示的なチェックを行う必要があります (あまり良い設計ではありません)。

したがって、どちらのループを使用しても実際には違いはありません... For each はより単純になり、欠点はありません。

于 2013-10-10T04:11:50.417 に答える