14

これは非常に単純な質問ですが、私はまだ非常に不安です。

クラスがアクセサメソッドを介してプライベートメンバーへの参照を返すことが現在広く受け入れられているのはなぜですか?これはカプセル化の原則を完全に破っていませんか?これでよければ、メンバーを公開してみませんか!?

public class EncapsulationViolator
{
  private object abuseMe;

  public object AbuseMe 
  {
    get { return abuseMe; }
  }
}

編集私が考えていたケースはこれです

EncapsulationViolator ev = new EncapsulationViolator();

object o = ev.AbuseMe;

o.SetValue(newValue);

メンバーabuseMeの状態が変更されたため、evの状態は推移性によって変化しました。

DDDのコンテキストでは、オブジェクトが集約ルートである場合、これはOKではありません。引用します

外部オブジェクトがルートへの参照のみを保持できるようにします。内部メンバーへの一時的な参照は、単一の操作内でのみ使用するために渡すことができます。ルートはアクセスを制御するため、内部の変更によって目隠しすることはできません。

[ドメイン駆動設計、エリックエバンス]

...セッターシュメッター..。

4

6 に答える 6

12

C ++の用語「参照」を、C#がオブジェクトを(参照の)値で渡すという事実と混同しています。

この場合、ゲッターの呼び出し元はプライベートフィールドを交換AbuseMeできません。したがって、カプセル化の違反はありません。abuseMe

EncapsulationViolator x = new EncapsulationViolator();
object y = x.AbuseMe;
y = 17; // I have not changed x.AbuseMe

Debug.Assert(y != x.AbuseMe); // Passes!

さらに、プロパティゲッターとセッターはプライベートフィールドの適切なカプセル化を可能にし、これらをメソッドとして実装するのと機能的に同じです(実際、これらはコンパイラーによってメソッドとして実装されます)。

プライベート変数を返すとカプセル化が破られる可能性がある1つのケースは配列への参照を返す場合です。

class X
{
    private int[] amazing = new int[10];

    public int[] Amazing { get { return this.amazing; } }
}

X a = new X();
int[] x = a.Amazing;
int[] y = a.Amazing;

x[2] = 9;
Debug.Assert(x[2] != y[2]); // Fails!
于 2012-07-18T15:10:17.097 に答える
10

メンバーがどのようなオブジェクトであるかによって異なります。たとえば文字列の場合、不変であるため、文字列を変更することはできません。

可変オブジェクトの場合、クラス外からオブジェクトの内容を変更することはできますが、オブジェクト自体を置き換えることはできません。

オブジェクトをクラスの外部から変更できないようにする場合、ゲッターはオブジェクトの不変バージョンを返す必要があります。

間違って行うと、パターンによってカプセル化が壊れる可能性がありますが、正しく実行された場合、カプセル化はそのままです。

于 2012-07-18T15:08:28.723 に答える
8

私はそれがカプセル化を壊すとは思わない。クラスは、の戻り値がどこAbuseMeから来るかを決定します。別のメンバーからのものである場合もあれば、毎回再作成またはコピーされる場合もあります。

ポイントは、クラスがユーザーにそのメンバーで何を許可するか(get / setまたはその両方とその可視性)を決定し、検証を実行して無効な値が設定されるのを防ぐことができ、ユーザーがその値の場所を知る必要がないことです。から来た。

また、get / setメソッドにカスタムロジックを追加する場合は、他のアセンブリとの互換性を損なうことなく追加できます。

于 2012-07-18T15:04:43.653 に答える
1

ゲッターとセッターのポイントは、特にカプセル化を強制することです。重要なのは、オブジェクトへの直接アクセスを許可するのではなく、定義した関数によってオブジェクトへのアクセスを強制することです。ゲッターとセッターはカプセル化です。オブジェクトを返すだけの場合、それはあなたの仕事ですが、ゲッターを押すことなく直接アクセスを許可することはできません。

これを読んでください:http: //en.wikipedia.org/wiki/Mutator_method

于 2012-07-18T15:11:00.080 に答える
1

単なる構文糖衣です。これは、JavaのgetXXXおよびsetXXXメソッドと何ら変わりはありません。

于 2012-07-18T15:05:30.627 に答える
1

IMO-ここでの回答が多すぎると、ゲッター/セッターが宣伝されます。ゲッター/セッターは手続き型コードに最適です。計算を行って結果を設定するか、値を取得して決定を下します。

オブジェクト指向プログラミングでよく知られている原則は、Tell do n't askです。これは、基本的に、内部状態のオブジェクトに決定を求めるべきではないと言っています。

そうは言っても、私はアクセサー/プロパティを自分で使用しています。ただし、可能な場合は避けてください。

于 2012-07-21T18:36:35.663 に答える