5

I have a question with regard to encapsulation. As I know, encapsulation enables to hide the implementation details using private/protected data members and provides public methods and properties to operate on the data. The idea here is to prevent the direct modification of the data members by the class consumers.

But I have a concern with the property getters or other public methods which return private/protected data members. For ex: if I have class like this

public class Inventory
{
    private List<Guitar> guitars = new List<Guitar>();

    public void AddGuitar(string serialnumber, string price)
    {
        Guitar guitar = new Guitar(serialnumber, price);
        guitars.Add(guitar);
    }

    public List<Guitar> GetGuitars()
    {
        return guitars;
    } 
}

Now if the Inventory class consumer calls GetGuitars, he is going to get the list of guitars being maintained in the Inventory class. Now the consumer can modify the list, like delete/add/modify the items. For me it looks like we are not encapsulating. I think that I should be returning a copy of the Guitar list items in the GetGuitars(). What do you think?.

Is my understanding of the encapsulation right?.

Thanks

4

6 に答える 6

1

リスクの観点からは、リストのコピーを返して変更不可能にする方が確かに優れています (関数型プログラミング スタイルのギターを追加すると、まったく新しい変更不可能なリストを作成します)。

カプセル化に関しては、getGuitars()メソッドを削除してから、Inventoryクラスがそれに関連付けられた機能を提供する必要があります (たとえば、printInventoryReport()その他のもの)。このように、クライアント クラスは、ギターの保管方法を知る必要がまったくなく、関連するコードをInventoryクラスに保持します。トレードオフは、このクラスが大きくなり、ギター リストから何か新しいものが必要になるたびに、 を変更する必要があることですInventory

良い記事をお勧めします: http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html 当時はかなり扇動的でしたが、そこには多くの真実があると思います.

そして、ゲッターを使用する場合、小さなヒントは、ゲッターにする必要があるか、ListそれともCollectionできる必要があるかを選択することです。たぶんIterable!このようにして、実装について可能な限り伝えることが少なくなり、カプセル化が向上します。

于 2012-10-04T08:21:39.797 に答える
1

あなたが正しいです。そのようなセッターを使用すると、クライアントはリストを変更できます。ギターを追加するために特別な処理が必要な場合、これは望ましくありません。この場合、次の 2 つの選択肢があります。

  1. リストのコピーを返します(すでに提案したように)。
  2. ゲッター内のReadOnlyCollectionでラップします。

クライアントがリストを外部から変更しようとしたときに「驚いた」ことがないように、両方のケースをメソッドの説明に記載する必要があります。

于 2012-10-04T08:18:26.407 に答える
1

オブジェクトのリストをカプセル化することは、適切なインターフェースを使用してオブジェクトへのアクセスを制限することで、うまく実現できます。

AddGuitar メソッドを介してリストへの追加を制御するのは正しいと思います。リストの代わりに IEnumerable を返すように GetGuitar を変更することで、この設計を強化できます。

これにより、呼び出し元がリストに対して持つコントロールが減少しますが、抽象型を返すこともコミットされません。このようにして、パブリック インターフェイスを変更する必要なく、内部データ構造を変更できます。

于 2012-10-04T08:14:33.247 に答える
1

リスト配列を変更できないようにしたい場合、AsReadOnly メソッドを使用しない理由: http://msdn.microsoft.com/en-us/library/e78dcd75.aspx

メンバー内のカプセル化については、メンバーが外部から利用できないメソッドを介してのみ書き込みおよび読み取り可能です。

于 2012-10-04T08:20:43.917 に答える
0

私は、リストを返すことで、カプセル化に関して何かが望まれることに同意します。個々のアイテムのゲッター、または場合によってはイテレーターの作成を検討することをお勧めします。このリストは実装の詳細のように見えるので、他のクラスは実際には直接アクセスするビジネスを持っていません。

于 2012-10-04T07:58:14.640 に答える
0

ここには (少なくとも) 2 つの問題があります。

1 つ目は、実装を非表示にすることです。「guitars」フィールドを配列またはデータベースに変更することもできますが、メソッド AddGuitar および getGuitars の署名を変更せずにそのままにして、クライアント コードが壊れないようにすることもできます。

2つ目は、ギターリストの防御コピーを返すかどうかです。ギターのリストを取得したら、要素を追加および削除しますか? ギターを追加する方法があるので、そうではないと思います。

于 2012-10-04T08:10:55.123 に答える