質問
セッターの引数を変更するのは正常ですか? setStringメソッドがあると想像しましょう。そして、私たちは本当に文字列のトリミングされた形を保ちたいです。したがって、末尾にスペースを含む文字列は無効ですが、例外をスローする必要はありません。
最良の解決策は何ですか?セッターで値をトリミングするには、たとえば
public void setString(String string) {
this.string = string.trim();
}
または呼び出し元でそれをトリムする(複数回)例:
object.setString(string.trim());
それとも他の何か?
解決
はい。結局のところ、セッターはこの種のことのために設計されています!フィールドに書き込まれる値を制御およびサニタイズするには;)
他のヒント
まったく。次に例を示します。さまざまな種類の測定単位を使用するエンジニアリングプログラムがあるとします。 1つの測定システムで内部値を保持しますが、セッターで他のすべてのシステムから変換し、ゲッターで変換します。例:
public double UserTemperature
{
get
{
return Units.Instance.ConvertFromSystem(UnitType.Temperature, temperature);
}
set
{
double v = Units.Instance.ConvertToSystem(UnitType.Temperature, value);
if (temperature != v)
{
temperature = v;
Changed("SystemTemperature");
Changed("UserTemperature");
}
}
}
はい、確かです。メソッド(trim()など)を適用する前に、NULLをチェックするよう注意してください。
2つの学校があります:1つはセッター(学校スタイル)でparamをチェックしてもよいと言います。
2番目の方法のほうがもっと信じています。 Beanの実装はどのくらいの頻度で見ますか? getUserは例外をスローするか、単にnullを返す必要がありますか?
セッターとゲッターにロジックを配置すると、多くの人がその実装を見ることはないので、何が起こっているのか理解しにくくなります。同意できない場合は、使用する前に、すべてのセッターとゲッターの実装を見て、Beanだけではないかどうかを確認することをお勧めします。
一見、最小限の驚きの原則に違反しているようです。私があなたのクラスのユーザーなら、セッターが私がそれを伝えることを正確に行うことを期待するでしょう。セッターで例外をスローして、ユーザーに入力のトリミングを強制します。
他の(より良い?)代替方法は、メソッドの名前をtrimAndSetStringに変更することです。そうすれば、入力をトリミングするのは驚くべき動作ではありません。
間違っている場合は修正しますが、セッターがこの種のロジックを保持する必要があることは論理的に見えます。 セッターがチェックせずに内部変数に値を割り当てているだけなら、なぜ変数自体を公開しないのですか?
これがまさに、オブジェクトフィールドを全世界に公開するのではなく、セッターを使用する理由です。
0から359までの整数の角度を保持するクラスを検討してください。
フィールドを公開する場合、関数を呼び出すと、フィールドを好きなように設定できます。これにより、APIで指定されたコントラクトが壊れます。また、コードはその変数の特定の範囲を想定して記述されているため、機能が軌道のどこかで壊れる可能性があります。
セッターを使用すると、いくつかのことができます。 1つは、無効な値が渡されたことを示す例外を発生させることですが、これは私のビューでは正しくありません(この場合)。次のように、入力値を0から359の間の値に変更すると、より便利になります。
actualVal = passedValue % 360;
これがインターフェイス(API)で指定されている限り、完全に有効です。実際、それを指定しなくても、呼び出し元が契約に違反しているため(範囲外の値を渡すことにより)、何でも自由に実行できます。 「できるだけ早く入力をサニタイズする」というルールに従う傾向があります。
特定のケースでは、文字列がトリミングされた形式で保存されるように指定している限り、呼び出し側が文句を言う理由はありません(そのような文字列は無効であると既に述べています)。セッターを呼び出すコードのすべての部分ではなく、セッターで実行する方が、コードサイズ(速度ではない)の点で優れています。また、文字列が期待どおりに保存されることを保証します-呼び出し元が誤って(または意図的に)トリミングされていない文字列を保存しないという保証はありません。
はい。オブジェクト指向設計の特徴は、呼び出し側がクラスをブラックボックスとして扱うことができることです。インターフェースの動作が文書化され論理的である限り、内部で行うことはあなた自身のビジネスです。
人によって哲学は異なりますが、プロパティセッターは、オブジェクトの状態の側面を指定された値と一致するように設定し、おそらく変更を気にする人に通知する場合にのみ適切であることをお勧めしますそれ以外の場合、オブジェクトの状態に影響します(プロパティセッターに関連付けられた状態に関してそのプロパティが定義されている場合、プロパティセッターが読み取り専用プロパティの値を変更することは完全に適切です。たとえば、コントロールの読み取り専用の Right
プロパティは、 Bounds
の観点から定義できます)。指定された操作を実行できない場合、プロパティセッターは例外をスローする必要があります。
クライアントが上記の説明を満たさずに何らかの方法でオブジェクトの状態を変更できるようにする場合は、プロパティではなくメソッドを使用する必要があります。 Foo.SetAngle(500)
を呼び出すと、メソッドは指定されたパラメーターを使用して角度を設定することが合理的に期待されますが、 Angle
プロパティは角度を返さない場合があります設定されたのと同じ形式で(たとえば、140を返します)。一方、 Angle
が読み取り/書き込みプロパティである場合、500の値を書き込むことは禁止されるか、値が500を読み返すことが予想されます。オブジェクトは0から359の範囲の角度を保存します。また、オブジェクトは BaseAngle
という読み取り専用プロパティを持ち、常にその形式で角度を返します。