80

重複の可能性:
ゲッターとセッターを使用する理由

Java に関する本を読んだことがxありyます。例えば:

public int getX(){
    return x;
}

public void setX(int x){
    this.x = x;
}

しかし、それとの違いは何ですか

...(shape.x)...   // Basically getX()

shape.x = 90;    // Basically setX()

セッターとゲッターが優れている場合、実際にはどのような問題が発生しますか?

4

13 に答える 13

87

複数の理由:

  • 次のようなフィールドアクセスを許可する場合

    形状.x = 90

その後、データを検証するためのロジックを追加することはできません。

x が 100 未満にならない場合は実行できませんが、次のようなセッターがあったとします。

public void setShapeValue(int shapeValue){
  if(shapeValue < 100){
    //do something here like throw exception.
  }
}
  • コピー オン ライト ロジックなどを追加することはできません ( CopyOnWriteArrayListを参照) 。
  • もう 1 つの理由は、クラス外のフィールドにアクセスするには、それらを public、protected、または default とマークする必要があるため、制御できなくなることです。データがクラスの非常に内部にある場合、カプセル化と一般的なOOPS方法論を破ります。

ただし、次のような定数の場合

public final String SOMETHING = "SOMETHING";

フィールドは変更できないため、フィールドへのアクセスを許可します。たとえば、変数をゲッター、セッターで配置します。

  • もう 1 つのシナリオは、クラスを不変にしたい場合です。フィールド アクセスを許可すると、値が変更される可能性があるため、クラスの不変性が失われます。しかし、ゲッターを使用してセッターを使用せずに慎重にクラスを設計すると、不変性をそのまま維持できます。

ただし、そのような場合、オブジェクトの参照を渡さないように getter メソッドに注意する必要があります (クラスにオブジェクトがインスタンスとして含まれている場合)。

ゲッターとセッターを使用して、任意のパッケージでプライベート変数を使用できます。

于 2012-05-02T04:54:29.947 に答える
12

getter 関数と setter 関数を使用すると、制約とカプセル化が可能になります。xが半径だとしましょう。shape.x = -10 はあまり意味がありません。また、誰かが不正な値を設定しようとした場合、エラーを出力するか、デフォルト値を設定するか、何もしないことができます。

メンバー変数を非公開にして、それを使用するプログラムが直接変更できないようにすることをお勧めします。

ミューテーター関数
のカプセル化

于 2012-05-02T04:51:41.970 に答える
4

ユーザーにとってもう1つの正当な理由でgetterありsetter、次の例で理解できます

public class TestGetterSetter{
    private String name ;


    public void setName(String name){
        this.name = name ;
    }


    public String getName(){
        return this.name ;
    }
}

ゲッターとセッターの要点は、取得または設定するプライベート変数にアクセスするためにのみ使用されることを意図しているということです。このようにしてカプセル化を提供すると、後でコードをリファクタリングまたは変更するのがはるかに簡単になります。

その の代わりに name を使用すると想像してくださいgetter。次に、デフォルトのようなものを追加する場合 (以前に設定されていない場合、デフォルトの名前は「Guest」です)、gettersayName関数の両方を変更する必要があります。

public class TestGetterSetter{
    private String name ;


    public void setName(String name){
        this.name = name ;
    }


    public String getName(){
        if (this.name == null ){
            setName("Guest");
        }
        return this.name ;
    }
}

getter と setter が get と set で始まる必要はありません。これらは単なる通常のメンバー関数です。ただし、それを行うのは慣習です。(特に Java Beans を使用する場合)

于 2012-05-02T05:18:08.750 に答える
4

ゲッターとセッターについて私が考えることができる最良の理由の 1 つは、クラスの API の永続性です。Python のような言語では、名前でメンバーにアクセスし、後でメソッドに切り替えることができます。プロパティにアクセスすると、関数はJavaのメンバーとは異なる動作をするためです。後でスコープを制限すると、クライアントが壊れます。

getter と setter を提供することにより、プログラマーは、パブリック API によって記述されたコントラクトに従う限り、メンバーと動作を自由に変更できる柔軟性を持ちます。

于 2012-05-02T05:06:54.910 に答える
3

もともと、ゲッター/セッター パターンは、外部encapsulatingの から内部のによって優れたオブジェクト指向設計を促進するために作成されました。 classinterface

  • プロパティの内部表現を隠す

これはあなたの質問に対する最良の答えですなぜゲッターとセッターを使うのですか?

于 2012-05-02T05:20:31.760 に答える
3

仮に、自分のクラス (YourClass) で行ってきたことをより適切に処理するライブラリを見つけたとします。この時点で行うべき自然なことは、 YourClass をそのライブラリへのラッパー インターフェイスにすることです。クライアントコードが取得または設定する必要がある「X」の概念がまだあります。当然のことながら、この時点で、アクセサー関数をほとんど作成する必要があります。

アクセサー関数の使用を怠り、クライアント コードが YourClass.x に直接アクセスできるようにした場合、YourClass.x に触れたことのあるすべてのクライアント コードを書き直す必要があります。ただし、最初から YourClass.getX() と YourClass.setX() を使用していた場合は、YourClass を書き直すだけで済みます。

プログラミング、特にオブジェクト指向プログラミングの重要な概念の 1 つは、実装の詳細を隠して、他のクラスやモジュールのコードで直接使用されないようにすることです。このように、実装の詳細を変更しても (上記の例のように)、クライアント コードは違いを認識せず、変更する必要がありません。クライアント コードが知っている限りでは、"x" は変数であるか、その場で計算される値である可能性があります。

これは単純化しすぎており、実装を非表示にすることが有益なすべてのシナリオをカバーしているわけではありませんが、最も明白な例です。実装の詳細を隠すという概念は、現在 OOP と強く結びついていますが、OOP が考案される何十年も前から議論されています。それはソフトウェア開発の核となる概念の 1 つに戻ります。大きな曖昧な問題を、簡単に解決できる明確に定義された小さな問題に分割するというものです。アクセサー関数は、小さなサブタスクを分離し、明確に定義するのに役立ちます。クラスが互いの内部構造について知らないほど、より良い結果が得られます。

于 2012-05-02T05:07:08.273 に答える
1

多くの理由があります。ここにいくつかあります。

  1. アクセサー、特にゲッターは、しばしばインターフェースに現れます。インターフェイスでメンバー変数を規定することはできません。
  2. このメンバー変数を公開すると、その実装方法について考えを変えることはできません。たとえば、「x」プロパティを実際にネストされたオブジェクトから取得する集計などのパターンに後で切り替える必要がある場合は、その値をコピーして同期を維持する必要があります。良くない。
  3. ほとんどの場合、セッターを公開しない方がはるかに優れています。x のような public フィールドではそれができません。
于 2012-05-02T04:54:16.650 に答える
1

答えに入る前に、事前に知っておかなければならないことがあります...!「JavaBeans」。
JavaBean は、プロパティを持つ Java クラスです。ここでは、プロパティをプライベート インスタンス変数と考えます。それらはプライベートであるため、クラスの外部からアクセスできる唯一の方法は、クラス内の「メソッド」を使用することです。
プロパティの値を変更するメソッドはセッター メソッドと呼ばれ、プロパティの値を取得するメソッドはゲッター メソッドと呼ばれます。

于 2012-05-02T04:57:37.230 に答える
0

オブジェクト指向プログラミング言語を使用しているからです。ここでは、データの隠蔽とカプセル化を使用しています。変数は(データの隠蔽を実現するために)外部の世界から直接アクセスできないようにする必要があるため、プライベートに作成します。

シェイプ.x

は正しくありません。カプセル化を実現する方法である x の値を取得および設定するには、getter メソッドと setter メソッドを使用します。

于 2012-05-02T05:06:11.827 に答える
0

ゲッター/セッターもパブリック メンバーも、優れたオブジェクト指向設計ではないと思います。どちらも、そもそもオブジェクトのプロパティにアクセスすべきではないオブジェクト データを世界に公開することで、OOP カプセル化を破ります。

于 2012-05-02T04:56:21.263 に答える
0

これは、OOPのカプセル化の原則を適用することによって行われます。

オブジェクトの一部のコンポーネントへのアクセスを制限するための言語メカニズム。

つまり、クラスの属性とメソッドの可視性を定義する必要があります。3 つの一般的な可視性があります。

  • プライベート: クラスのみが属性/メソッドを表示および使用できます。
  • 保護: クラスとその子のみが属性/メソッドを表示および使用できます。
  • パブリック: すべてのクラスが属性/メソッドを表示および使用できます。

private/protected 属性を宣言するときは、値を取得 (get) し、値を変更 (set) するメソッドを作成することをお勧めします。可視性に関する 1 つの例は[ArrayList][2]クラスですsize。内部配列の実際のサイズを知るためのプロパティがあります。クラスのみがその値を変更する必要があるため、コードは次のようになります

public class ArrayList<E> {
    private int size;
    private Object[] array;
    public getSize() {
        return this.size;
    }
    public void add(E element) {
        //logic to add the element in the array...
        this.size++;
    }
}

この例では、サイズ値はクラス メソッド内でのみ変更できることがわかります。実際のサイズは、コード内で呼び出すことで取得できます (変更するのではありません)。

public void someMethod() {
    List<String> ls = new ArrayList<String>();
    //adding values
    ls.add("Hello");
    ls.add("World");
    for(int i = 0; i < ls.size(); i++) {
        System.out.println(ls.get(i));
    }
}
于 2012-05-02T04:57:03.057 に答える
0

ゲッターとセッターは、パブリック メソッドを介してのみアクセスできるようにすることでクラスのフィールドをカプセル化し、値自体をプライベートに保ちます。これは、優れた OO 原則と見なされます。

確かに、値を設定したり返したりするだけの場合、冗長なコードのように見えることがよくあります。ただし、セッターを使用すると、入力の検証またはクリーンアップも実行できます。それを 1 か所にまとめることで、オブジェクトのデータの整合性が向上し、

于 2012-05-02T04:57:03.157 に答える