web-dev-qa-db-ja.com

Javaでゲッターとセッターメソッドが重要なのはなぜですか?

私は常にゲッターとセッターを使用するように教えられてきました。しかし、これらのメソッドの長所と短所は知りません。それらを実装することで、データを公開し、非表示にしているからです。

私はこれについて少し混乱しています。ゲッター/セッターを使用する理由とその利点について、適切なアドバイスを提供できますか?

35
School Boy

基本的な「フィールドを返すか設定するだけのパブリックgetterおよびsetterを持つプライベートフィールド」パターンは、カプセル化に関してはまったく意味がありません。ただし、APIを変更せずに後で変更することができます。

そのため、そのパターンを考えずに使用しないでください。実際に必要な操作を慎重に検討してください。

ゲッターとセッターの本当のポイントは、適切な場合にのみ使用し、フィールドを取得および設定する以上のことができるということです。

  • ゲッターのみを使用できます。次に、プロパティは読み取り専用です。これは実際には最も一般的なケースです。
  • あなたはセッターのみを持つことができ、プロパティを構成可能にしますが、他には何もその値に依存すべきでないことを伝えます
  • ゲッターは、1つのフィールドを返すのではなく、複数のフィールドから値を計算できます。
  • ゲッターは防御的なコピーを作成できます
  • ゲッターは高価なフェッチ操作を遅延して実行し、フィールドを使用して値をキャッシュできます
  • セッターは健全性チェックを行い、IllegalArgumentExceptionをスローできます。
  • セッターは値の変更をリスナーに通知できます
  • 概念的に一緒に属するため、複数のフィールドを一緒に設定するセッターを持つことができます。これはJavaBeans仕様に準拠していないため、JavaBeansを期待するフレームワークまたはツールに依存している場合は、JavaBeans仕様に準拠しないでください。それ以外の場合は、便利なオプションです。

これらはすべて、実装の詳細であり、単純な「getter and setter」インターフェースの背後に隠されています。それがカプセル化の目的です。

64

ゲッターとセッターの考え方は、クラス内の変数へのアクセスを制御することです。そうすれば、値を別の方法で表現するために内部的に変更する必要がある場合、クラス外のコードを壊すことなく変更できます。

たとえば、距離変数を持つクラスがあり、それがインチで測定されたとしましょう。数か月が経過すると、このクラスを多くの場所で使用していて、その値をセンチメートルで表す必要があることに突然気付きます。ゲッターとセッターを使用しなかった場合、クラスの使用をすべて追跡し、そこで変換する必要があります。ゲッターとセッターを使用した場合は、それらのメソッドを変更するだけで、クラスを使用するすべてが壊れることはありません。

public class Measurement
{

    /**
     * The distance in centimeters.
     */
    private double distance;

    /**
     * Gets the distance in inches.
     * @return A distance value.
     */
    public double getDistance()
    {
        return distance / 2.54;
    }

    /**
     * Sets the distance.
     * @param distance The distance, in inches.
     */
    public void setDistance(double distance)
    {
        this.distance = distance * 2.54;
    }
}
17
Robert Rouhani

良い利点の1つは、特定のフィールドにセッターを実装しないことで、フィールドReadOnlyを作成できることです。

7
Sandeep Pathak

ここに欠点があります。ゲッター/セッターは、クラスの実装の詳細を外部に公開する傾向があります。それは良いことではありません。オートメカニックソフトウェアパッケージを書いているとします。したがって、Carクラスが必要になるため、フィールドのゲッターとセッターを公開します

Date lastOilChangeDate;
int lastOilChangeMileage;

このクラスで。これは、顧客の車にオイル交換が必要なときにソフトウェアがメールを送信するためです。

しかし、車が「3000マイルごとまたは3か月ごと」とは異なる方法でオイル交換が必要かどうかを判断する新しい車が出てきたらどうなりますか?これらの新しい車には、オイルパンに汚れを測定するセンサーが搭載されている可能性があります。明らかに、これを使用して、オイル交換が必要かどうかを判断します。

問題は、それらのゲッター/セッターで間違った問題を解決していたことです。最後のオイル交換がいつ行われたかを知りたがる人は誰もいません。それらは実装の詳細にすぎませんが、インターフェイスの一部にしたのです。あなたがすべきであったことは、メソッドを追加しました

public boolean needsOilChange() 

そして、Carクラスは必要に応じて実装できます。アルゴリズムが変更された場合、必要なのはneedsOilChangeメソッドだけだったため、Mechanicクラスは必要ありません。

3
MeBigFatGuy

singゲッターとセッターには何も問題はありません-byを使用し、それらをすべて公開すると、変数を公開し、ある意味でカプセル化に違反することに注意してください。これは、あなたが言及している記事が警告しようとしていることです-すべてのプライベートインスタンス変数のゲッターとセッターを自動的に生成しないでください。必要な場合にのみ公開するように、他のクラスに公開するもの(およびどのレベル、つまりprivate/protected/public)について考えます。

2