クラスでは通常、グローバル変数とローカル変数を宣言します。私はほとんどの場合、グローバル変数、セッター、ゲッターを宣言するのを見てきました。これらは毎回必須ですか?それらを使用せずに実装できても問題ありませんか?
4 に答える
一般に、変数、メソッド、クラスなどの可視性の範囲を常に縮小するようにしてください。
したがって、1 つの呼び出しシーケンスで使用される変数が必要な場合は、ローカル変数とメソッド引数を使用して、その値をメソッドからメソッドに渡します。たとえば、2 つのメソッドfoo()
とbar()
whilefoo
呼び出しがありbar
ます。
public void foo() {
bar();
}
private void bar() {
}
いくつかのサフィックスを追加した同じ文字列で両方が機能するとしましょう。次の例のように、ローカル変数を使用できます。
public String foo(String s) {
s += "foo1"
bar(s);
s += "foo2"
return s;
}
private String bar(String s) {
s += "bar1"
return s;
}
またはクラスレベル変数:
private String s;
public String foo() {
s += "foo1"
bar();
s += "foo2"
return s;
}
private String bar() {
s += "bar1"
return s;
}
次の理由により、最初の方法の方が優れています。
- それはカプセル化されています。誰も実装の詳細を知りません。誰も外部から影響を与えることはできません。
- 読みやすくなっています。どのオブジェクトが実装に参加しているかを理解するために、コードを前後に移動する必要はありません。
- オブジェクトレベルの変数を使用しないため、同期ブロックやアトミック変数などの特別な作業をしなくてもスレッドセーフです。
2 番目の実装はカプセル化されていません。オブジェクトの状態を変更し、次の の呼び出しに影響を与えるコードを追加できますfoo()
。アルゴリズムと、アルゴリズムによって影響を受ける変数の両方を理解するには、クラスを前後に移動する必要があります。スレッドセーフではありません。同じコードを実行する 2 つの同時スレッドが、同じ変数の変更で競合する場合があります。
グローバル変数とは、クラス メンバー フィールドのことですか? 変数がメソッドのスコープ内でのみ使用される場合は、ローカルにする必要があります。変数が基本的にクラス インスタンス全体の状態情報を保持している場合は、クラス メンバー フィールドとして宣言する必要があります (セッターとゲッターを使用して、他のクラスにこれらのフィールドへのアクセスを許可する必要がある場合)。
Java クラスの概要はこちら: http://docs.oracle.com/javase/tutorial/java/javaOO/summaryclasses.html
「グローバル変数」をメンバーフィールド変数(メソッドのコンテキスト外で定義)として定義していると思います。実装を簡単に変更できるように、メンバー フィールドを使用する場合はミューテーター (セッター) とアクセサー (ゲッター) を使用することをお勧めします。1 つの良い例は、変数の状態を取得または設定するときにフィールドの周囲の条件をチェックしている場合、使用するたびに分散するのではなく、1 つの場所で変更をカプセル化できることです。
Java にはグローバル変数がありません。
フィールドは、オブジェクトのプロパティである場合にのみ存在する必要があります。たとえば、オブジェクトの 2 つのメソッド呼び出し間の中間結果を格納するために使用しないでください。
ゲッターは、外部から情報にアクセスする必要がある場合にのみ定義する必要があります。必要がない場合は、ゲッターを定義しないでください。プライベートな状態が多いほど、他のクラスに影響を与えずにクラスを進化させることができるため、最高です。
セッターは、フィールドの変更が必要な場合、およびこのフィールドを他のフィールドとは別に変更することが理にかなっている場合にのみ変更する必要があります。
良いルール:
- 少ない状態は多い状態よりも優れている
- 不変状態は可変状態よりも優れています
- メソッドは常に、オブジェクトを安定した一貫性のある状態から別の安定した一貫性のある状態に移行する必要があります。