たとえば、リストを含むクラスがあります。
class User{
....
List<String> cards
...
}
このメンバーへのアクセスを提供する最良の方法は何ですか?
List<String> getCards()
または
String getCard(int index)
次のようなnullポインター例外を回避できるように、2番目のオプションに誘惑されます。
getCards().get(0) //if getCards() returns null
しかし、それはクラスの責任であってはならないことでもあるのでしょうか。
この回答はC#の観点から書かれています。 C#インターフェイスをJava=の同等物に置き換えるか、必要に応じて2つの言語間の不一致または同等物の欠如に言及するように編集してください。
エヴァンの答えは、物事をシンプルに保つという点で価値があります(KISS)。
RobertBräutigamの回答に入る前に、このタスクが伝統的にどのようにJava開業医によって処理されているか)を見てみましょう (私はそうではありません):
Card
オブジェクトまたはAbstractCard
インターフェイス(String
を使用する代わりに)、UserCardConsumer
インターフェイスまたは抽象クラス(または略してCardConsumer
)。一度に1枚のカード、または一度にカードのコレクション全体を受け入れるメソッドを定義します。これは継承可能であることを意味します(実装または拡張されます)。User
からカードを「消費」するビジネスロジックは、UserCardConsumer
から継承する内部クラスを実装する必要があります。これは、メソッドが呼び出されたときにカードを消費します。伝統的なコード(Javaは有名である)の追加の量を考えると、RobertBräutigamは、アプリケーション。そのCard
コレクションで動作するロジック全体を1つのクラスにカプセル化できる場合は、それを使用してください。
User
クラスが何である必要があるかを決定します。通常、複数のニーズが存在します。
getCard(int index)
メソッドを公開する場合、呼び出し元がforループを使用できるように、int getCardCount()
メソッドも公開する必要がある場合があります。
さまざまな理由により、可変の_List<String>
_メンバーを公開する(つまり、内部メンバーへの参照を呼び出し元と共有する)ことが不確かな場合は、いくつかのオプションがあります。
IReadOnlyList<>
_(不変。それ以外はリストのように動作します)IList<>
_(おそらく変更可能、それ以外はリストのように動作します)IList
インターフェースも提供しますが、それらのミューテーターは例外をスローします。IReadOnlyList<>
_を公開することは_IList<>
_よりも優れていることを示唆しています。IList<>
_が選択されます。ICollection<>
_ ...これはまさにあなたが望むことをします:Count
プロパティがあるため、_user.Cards.Count
_を実行できますuser.Cards[2]
_を実行できますICollection<>
_は_IEnumerable<>
_よりも優れた選択肢です。ICollection<>
_ にはないにはAdd(T)
メソッドがあります。User
クラスに配置できるため、これは問題にはならない場合があります。これにより、User
にリストへの変更が通知され、必要に応じてオブジェクトの不変条件を維持するための追加のアクションを実行できるようになるため、さらに好ましいです。一貫性と同期の維持に関する問題。
単純なアプリケーションの場合、これは大きな問題ではない可能性があります。
少し複雑なアプリケーションの場合、変更可能なデータ転送オブジェクトは、アイテムのスナップショット(コピー)リストを返すことができます。その後のリストの変更は、以前に返されたコピーされたリストと同期されません。
Null例外の防止。
私の典型的なアプローチは次のとおりです。
List
メンバーreadonly
をマークします。つまり、同じリストが常に使用(および再利用)され、変更やアイテムの削除後も存続します。つまり、このリストへの参照は常に同じになります。User
コンストラクター内で、このList
メンバーを初期化します。これをreadonly
キーワードと組み合わせると、このリストへの参照が常に同じでnull以外になることが保証されます。IList<>
_として公開します。または_IReadOnlyList<>
_List
で実行されます。オブジェクト指向および保守可能な設計に興味がある場合は、注目に値しますそのリストをまったく公開しないでください。
もちろん、まれな例外もありますが、一般的にオブジェクト指向は、データを非表示にし、オブジェクトを与えることですそのデータを操作する動作。
データまたは純粋なデータ構造を公開するたびに、本質的にそのデータを制御できなくなります。これは、メンテナンスにとって本当に悪いことです。意味のある動作を維持する代わりに、任意の(つまり技術的な)データインターフェイスを維持する必要があります。
したがって、「最善」のオプションは、そのようなことがある場合、アプリケーション全体が必要とするものを調べ、その動作のプールからメソッドを選択することです。ローカルでだけでなく、どのデータを取得するかを考えるのではありません。開発者として。