大学でC ++を学ぶときに、講師と同様の議論をしたことを覚えています。変数をパブリックにできるとき、ゲッターとセッターを使用する意味がわかりませんでした。私は長年の経験で今よりよく理解し、単に「カプセル化を維持する」と言うよりも良い理由を学びました。
ゲッターとセッターを定義することにより、一貫したインターフェースを提供するため、実装を変更する必要がある場合に、依存するコードが破損する可能性が低くなります。これは、クラスがAPIを介して公開され、他のアプリまたはサードパーティで使用される場合に特に重要です。それでは、ゲッターまたはセッターに入るものはどうでしょうか?
一般に、ゲッターは値にアクセスするための単純なバウンドパススルーとして実装するほうが適切です。これにより、ゲッターの動作が予測可能になります。一般的に言うと、計算や条件付きコードで操作される値にアクセスするためにゲッターが使用されているケースを見てきました。一般に、設計時に使用する視覚的なコンポーネントを作成する場合はあまり良くありませんが、実行時には便利なようです。ただし、これと単純なメソッドの使用との間に実際の違いはありません。ただし、メソッドを使用するときは、一般的にメソッドをより適切に命名する可能性が高いため、コードを読み取るときに「getter」の機能がより明確になります。
以下を比較してください。
int aValue = MyClass.Value;
そして
int aValue = MyClass.CalculateValue();
2番目のオプションでは、値が計算されていることが明確になりますが、最初の例では、値自体について何も知らずに値を返すだけであることがわかります。
おそらく、次のことがより明確になると主張できます。
int aValue = MyClass.CalculatedValue;
ただし、問題は、値が既に他の場所で操作されていると仮定していることです。したがって、ゲッターの場合、値を返すときに他の何かが起こっていると仮定したいかもしれませんが、プロパティのコンテキストでそのようなことを明確にすることは難しく、プロパティ名には動詞が含まれてはいけませんそうしないと、アクセス時に使用する名前に括弧を付ける必要があるかどうかを一目で理解することが難しくなります。
ただし、セッターはわずかに異なるケースです。プロパティに送信されるデータを検証するためにセッターがいくつかの追加処理を提供し、値の設定がプロパティの定義された境界に違反する場合に例外をスローすることが完全に適切です。ただし、一部の開発者がセッターに処理を追加する際に問題になるのは、何らかの方法でデータの計算や操作を実行するなど、セッターにもう少しやらせたいという誘惑が常にあることです。これは、場合によっては予測不能または望ましくない副作用を得ることができる場所です。
セッターの場合、私は常に単純な経験則を適用します。これは、データに対してできる限り実行しないことです。たとえば、通常は境界テストと丸めを許可して、必要に応じて例外を発生させるか、必要に応じて例外を賢明に回避できるようにします。浮動小数点プロパティは、例外の発生を回避するために余分な小数点以下を丸める一方で、小数点以下数桁を追加して範囲内の値を入力できるようにする良い例です。
セッター入力のある種の操作を適用すると、ゲッターと同じ問題が発生します。単にセッターに名前を付けるだけでは、セッターが何をしているかを他の人に知らせることは困難です。例えば:
MyClass.Value = 12345;
これは、セッターに与えられたときに値に何が起こるかについて何か教えてくれますか?
どうですか:
MyClass.RoundValueToNearestThousand(12345);
2番目の例では、データに何が起こるかを正確に示しますが、最初の例では、値が任意に変更されるかどうかを通知しません。コードを読むとき、2番目の例はその目的と機能がより明確になります。
これは、最初にゲッターとセッターを持つという目的を完全に無効にし、検証と他のロジック(もちろん、奇妙な副作用なし)を許可する必要があると思いますか?
ゲッターとセッターを持つことは、「純度」のためのカプセル化ではなく、クラスのインターフェイスへの変更を危険にさらすことなくコードを簡単にリファクタリングできるようにするためのカプセル化に関するものです。セッターでは検証は完全に適切ですが、呼び出しコードが特定の方法で発生する検証に依存している場合、検証の変更により呼び出しコードとの互換性が損なわれる可能性があるという小さなリスクがあります。これは一般的にまれで比較的リスクの低い状況ですが、完全を期すために注意する必要があります。
検証はいつ行われますか?
実際に値を設定する前に、セッターのコンテキスト内で検証を行う必要があります。これにより、例外がスローされた場合、オブジェクトの状態が変化せず、データが無効になる可能性がなくなります。通常、セッターコードを比較的すっきりさせるために、セッター内で最初に呼び出される別のメソッドに検証を委任する方が良いと思います。
セッターは値の変更を許可されていますか(有効な値を標準的な内部表現に変換する可能性があります)?
非常にまれなケースでは、多分。一般的には、しない方がよいでしょう。これは、別の方法に任せるのが最善の種類です。