web-dev-qa-db-ja.com

リストまたはコレクションを使用する方が良いですか?

いくつかのデータをリストに格納するオブジェクトがあります。実装は後で変更される可能性があるため、内部実装をエンドユーザーに公開したくありません。ただし、ユーザーはこのデータのコレクションを変更してアクセスできる必要があります。現在、私はこのようなものを持っています:

public List<SomeDataType> getData() {
   return this.data;
}

public void setData(List<SomeDataType> data) {
   this.data = data;
}

これは、内部実装の詳細が漏洩することを許可したことを意味しますか?代わりにこれを行う必要がありますか?

public Collection<SomeDataType> getData() {
   return this.data;
}

public void setData(Collection<SomeDataType> data) {
   this.data = new ArrayList<SomeDataType>(data);
}
36
Vivin Paliath

状況によって異なりますが、ユーザーがデータにインデックスを作成できるようにしますか?はいの場合は、リストを使用します。どちらもインターフェースであるため、実装の詳細を漏らすことはありません。実際には、必要な最小限の機能を決定するだけで済みます。

25
Matt H

リストを返すことは、最も適切なインターフェースへのプログラミングと一致しています。

コレクションを返すと、ユーザーにあいまいさが生じます。返されるコレクションは、Set、List、またはQueueのいずれかである可能性があるためです。

18
Shikhar Mishra

List.get(int)を介してリストにインデックスを付ける機能とは関係なく、ユーザー(またはあなた)は、コレクションの要素が信頼性が高く予測可能な順序になっていることを期待していますか?コレクションに同じアイテムを複数含めることはできますか?これらは両方とも、より一般的なコレクションには一般的ではないリストへの期待です。これらは、エンドユーザーに公開する抽象化を決定するときに使用するテストです。

9
Brian M. Carr

高い階層にあるインターフェイスまたはクラスの実装を返す場合、経験則では、宣言された戻り値の型は、呼び出し元に保証する準備ができている最小限の機能を提供する最高レベルである必要があります。合理的に必要です。たとえば、実際に返すものがArrayListであるとします。 ArrayListは、(とりわけ)ListとCollectionを実装します。呼び出し元がget(int x)関数を使用する必要があると予想される場合、コレクションを返すことはできません。リストまたはArrayListを返す必要があります。リスト以外のものを使用するように実装を変更する理由がわからない限り(たとえば、セット)、正しい答えはリストを返すことです。 Listにない関数がArrayListにあるかどうかはわかりませんが、ある場合は、同じ理由が当てはまります。一方、コレクションではなくリストを返すと、実装がある程度ロックされます。 APIの設定が少なければ少ないほど、将来の改善に対する制限も少なくなります。

(実際には、そのような状況ではほとんどの場合リストを返しますが、それが私を燃やしたことはありません。しかし、おそらく本当にコレクションを返す必要があります。)

8
Jay

最も一般的なタイプであるCollectionを使用することは、より具体的なタイプであるListを使用する明確な理由がない限り、最も理にかなっています。しかし、何をするにしても、これが一般消費者向けのAPIである場合は、ドキュメントでそれが何をするのかを明確にしてください。コレクションの浅いコピーが返される場合は、そう言ってください。

5
Alb

はい、メソッドが常にリストを返すことがインターフェイスコントラクトの一部でない場合、最初の選択肢は実装の詳細をリークします。また、ユーザーコードがコレクションインスタンスを置き換えることを許可すると、渡される実装が期待どおりに動作しない可能性があるため、やや危険です。

もちろん、それはすべてあなたがあなたのユーザーをどれだけ信頼するかという問題です。 Python「私たちはすべてここで大人に同意している」という哲学を採用している場合、最初の方法で問題ありません。ライブラリが経験の浅い開発者によって使用されると思われる場合は、次のことを行う必要があります。彼らに「ベビーシッター」をして、彼らが何か悪いことをしないことを確認するためにできることはすべて、彼らにコレクションを設定させず、実際のコレクションを返さないことが望ましいです。代わりに、その(浅い)コピーを返します。

1
EMP

それはあなたがユーザーに提供したい保証に依存します。要素の順序が重要であり、重複を許可するようにデータが連続している場合は、リストを使用します。要素の順序が重要でなく、重複が許可される場合と許可されない場合がある場合は、コレクションを使用してください。基になるコレクションを実際に返すので、get関数とset関数の両方を使用する必要はなく、返されるコレクションが変更される可能性があるため、get関数のみを使用する必要があります。また、集合関数を提供すると、コレクションのタイプをユーザーが変更できるようになりますが、特定のタイプをユーザーが制御したい場合があります。