2

オブジェクト指向プログラミングでのゲッター/セッターの使用についていくつか読んだことがありますが、このような多くのリソースは、ゲッター/セッターの使用頻度は非常に低いことを示唆しています。その記事からの引用は次のように述べています。

仕事をするために必要な情報を求めないでください。情報を持っているオブジェクトに作業を依頼してください。

原則としては良さそうに思えますが、どのように実装するのが最適かは特にわかりません。車を説明するクラスがあるとします。そのクラス内で、クラスに格納されているこの車のブランドが「トヨタ」であるとしましょう。これで、これが「トヨタ」であることを表示する GUI ができました。ゲッターなしでどうやってそれを行うのですか?

「Toyota」が文字列として格納されていることを抽象化し、「Toyota」が既に書き込まれている TextBox を返したとしても、これはせいぜい、元のプロパティのラップされた形式のゲッターのように聞こえます。TextBoxes のようなものは GUI のクラスだけにあるべきであり、ここでの車のクラスのようなヘルパー クラスにあるべきではないと思っただけです。

4

4 に答える 4

3

その記事では、プロパティのゲッター/セッターの代わりにメソッドを使用する必要があると説明しています。基本的に、セッターが状態を変更できるようにするのではなく、メソッドが状態を変更するアクションを実行する必要があることを示唆しています。たとえば、Month プロパティと Day プロパティを持つクラスを作成できます。次に、これを行うコードを作成できます。

obj.Day = 28;
obj.Month = Months.February;
obj.Day = 30;
obj.Month = Months.March;

月が 2 月のときに 1 日を 30 に設定すると、状態が無効になります。

この記事では、クラスはこの種のことを許可するべきではなく、特定のアクションを実行するための特定のメソッドを提供する必要があることを示唆しています。

obj.ChangeDate(Months.March, 30);

DateTime が原因で日時の類似性がわかりにくい場合は、緯度/経度座標を使用した同様の例を使用できます。

obj.Latitude = 45.4112;
obj.Longitude = -75.6981;
//... 
obj.Latitude = 39.73;
obj.Longitude = -86.27;

緯度が 39.73 に設定されている場合、場所は、オタワ (最初の緯度/経度) またはインディアナポリス (2 番目の緯度/経度) ではなく、ニューアークの近くの場所になります。緯度/経度の設定をそのままにしておくと、インターフェイスが開いたままになり、その不変条件を検証できなくなり、真のオブジェクト指向ではないと言う人もいるかもしれません。したがって、代わりにメソッドを使用できます。

obj.MoveTo(39.73, -86.27);

OO は、カプセル化された状態と動作の両方を意味します。プロパティが状態を「カプセル化」していると考える人もいますが、通常はそうではありません。プロパティのバッキング ストアとして使用されるものを変更できるように、インターフェイスから実装を分離しますが、変更されることはめったにありません。したがって、プロパティは、パブリック フィールドを提供するのとは異なる方法で実装の詳細を利用できるようにするだけです。

インターフェイスが状態またはクエリ状態のいずれかを更新する必要があるが、両方を更新する必要がないことを示唆する、この考えに基づいたコマンド クエリ分離のような概念があります。ゲッターとセッターの両方を持つプロパティは、状態の更新と状態のクエリの両方を行うインターフェイスを提供します。上記の例MoveToChangeDateは、「コマンド」になります。概念的には、状態を照会する他の方法を提供します。それが必要な場合。

プロパティに関するその他の問題の 1 つは、単にプロパティであるという理由だけで、getter と setter の両方を習慣的に追加することです。プロパティを取得または設定する機能は必要ない場合があり、単純に getter と setter の両方を追加するだけで、必要とされないテストとメンテナンスを必要とするインターフェイスが作成されます。

微妙?もちろん; しかし、彼が話しているのはオブジェクト指向の設計であり、「機能する」コードではありません。

于 2012-08-29T22:40:56.137 に答える
2

あなたは「仕事をする」ことを無視しています。実行したい作業が車のブランドである場合、ブランドを返す getter が作業を行います。

記事が言っていることは、クラスデータで作業を行いたい場合は、作業をクラスに入れるということです。クラスからデータを引き出すのではなく、データを処理してからクラスに返します。

var c = new Car();
c.Odometer += 10;  // bad
c.DriveMiles(10);  // good

また、その記事が C# にどの程度当てはまるかについても疑問があります。それは主張します:

ゲッター メソッドとセッター メソッド (アクセサーとも呼ばれます) は、パブリック フィールドが危険であるのと同じ理由で危険です。実装の詳細への外部アクセスを提供します。

C# では、これは false です。C# アクセサーは任意のクラスを受け入れることができますが、「実装の詳細への外部アクセスを提供しません」。

于 2012-08-29T22:51:33.653 に答える
1

ゲッターとセッターは悪いものではなく、すべての属性に対して自動的に生成されるべきではありません。あなたの例に関する限り、Car クラスにはおそらく String を返す getBrand メソッドが必要ですが、この属性のセッターはおそらく必要ありません。ブランド名を含む TextBox を返す Car のメソッドは、単純な getter が String を返すよりもおそらく悪い考えです。これはあまり一般的ではないためです。

ピーター・リッチーの答えは今見ることができます: changeDate の良い例です。Date クラスは、日と月の getter を提供し、ユーザー コードでカレンダーの次の日を独自に計算する必要があるのではなく、そのようなメソッドを提供する必要があります。

于 2012-08-29T22:50:49.033 に答える
1

基本的に彼が言っているのは、10 個のプロパティを持つクラスがあり、それを csv の行にダンプしたいとします。Tocsv メソッドをクラスに追加して、csv の山を含む文字列を返します。プロパティを介してアクセスし、csv 文字列を作成する他のクラスを作成しないでください。必要に応じて非常に密結合になるためです。

なぜ彼がアクセサーを選んだのかはわかりませんが、問題は取得および設定するための個別のメソッドとまったく同じであり、さらに悪いことにメンバー変数です。

明らかに制限があります。交換するには本当に正当な理由が必要です。

SomeLabel.Text = SomeInstance.StringValue;

SomeInstance.MakeStringValueALabel(SomeLabel);
于 2012-08-29T23:05:30.357 に答える