9

Java クラスでは、getter と setter を使用してメンバー フィールドにアクセスするのは良い習慣ですか、それとも悪い習慣ですか?

たとえば、どちらが良いですか:

public Order {
    private Agreement agreement;

    public Agreement getAgreement() {
    return agreement;
    } 

    public void process() {
       //should I use:
       getAgreement().doSomething();
       //Or:
       agreement.doSomething();
    }
}

一般に、KISS の原則により、フィールドに直接アクセスするのが最善であり、誰かが後で get メソッドをオーバーライドして予測できない結果になる可能性があると思います。

しかし、私の同僚は、抽象化のレイヤーを保持する方が良いと主張しています。これについてコンセンサスはありますか?

4

11 に答える 11

9

正直なところ、私の意見では、それは使用目的によって異なります。個人的には、疑わしい場合は、後でサブクラスでオーバーライドする必要がある場合に備えて、余分なレベルの抽象化を常にそこに残します。ゲッターまたはセッターをオーバーライドできる状態にしておいたという理由だけで、クラスを書き直すという苦痛から救われたことが何度もありました。

もう 1 つのことは、他のクライアント/プログラマーが、あなたがまだ考えていない方法であなたのクラスを使用する必要があるかもしれないということです。たとえば、Agreement クラスをデータベースから引き出すなどです。その場合、彼らがあなたのクラスをオーバーライドするとき、あなたは彼ら (または潜在的にあなた) がそのデータの取得方法を変更するのを簡単にしました。

そのため、そのフィールドにアクセスする方法が 1 つしかなく、それが 100% 直接的であることが絶対に確実でない限り、値の取得と変更を切り離して、将来のある時点で書き直しの苦労を避けることができるようにするのがおそらく最善です。

于 2009-07-07T21:47:43.283 に答える
8

ここでの中心的な問題は、フィールドへの直接アクセスは、サブクラスのオーバーライドされたメソッド、AOP、動的プロキシなどによるインターセプトの対象外であるということです。これは場合によって、良いことにも悪いことにもなり得ます。内部でゲッターとセッターを使用することは、アンチパターンでもパターンでもありません。状況とクラスの設計に応じて、良いことも悪いこともあります。

于 2009-07-07T21:53:04.300 に答える
7

クラスのパブリック インターフェイスは、状態に関するカプセル化を表していると思います。そのため、クラスの他の動作でさえ、そのカプセル化の恩恵を受けます。

public get メソッドでフィールドをラップした場合は、その理由があります。おそらく、そのメソッド内に、フィールドを遅延ロードしたり、監査証跡を提供したりするロジックがあります。メソッドの理由が何であれ、クラスにはおそらくそのロジックも必要です。

于 2009-07-07T21:42:07.647 に答える
4

一部の人々は、この質問を外部で使用されるゲッターとセッターに関するものとして解釈しているように思えます。Pablojimの質問の私の解釈は、クラスがそのフィールドに直接アクセスするのではなく、クラス内でそれらを使用することに関するものであるというものでした。(これはプライベートです。)

その観点から、私はジェリコとパトロスと一緒です。特別な理由がない限り、クラス内から直接アクセスを使用してください。

于 2009-07-07T22:08:43.753 に答える
2

抽象化のレイヤーを維持することは、Java では良いことです。

問題は、クラスの制御下にないことをクラスが認識せずにメンバー変数に直接アクセスするすべてのコードです。

したがって、例として部門で使用される 1 つのメンバーが 0 にならないようにクラスを編集することを決定した瞬間、この値がこれを保証する方法でのみ変更されるようにする必要があります。したがって、このメソッドのセッターを追加し、メンバーをプライベートに変更します。しかし、セッターなしでメンバーにアクセスしているすべてのコードを変更する必要があります。
クラスの外部から値を変更していることがわかっている場合は、変数をプライベートにすることがわからない場合にのみセッターを提供し、後でアクセスする必要がある場合は、ゲッターまたはセッターを提供します。

メンバーに対して常に get を使用し、いくつかの計算を実行してから get を使用する特定のメソッドが他のオブジェクトにある場合、アンチパターンを取得します。これは、メンバーが他のクラスにある必要があるか、メソッドがこのクラスにある必要があることを示しています。

メンバーごとに考えずに getter と setter を持つことは、カプセル化を壊し、良い設計上の選択ではありません。詳細については、この記事をお読みください

于 2009-07-07T21:45:10.667 に答える
1

私は現在、ゲッターを支持する何かに取り組んでいます。現在、プロパティの一部を「プロパティ バッグ」に移動しています。つまり、変数を参照することはできません。したがって、ゲッターの変更に加えて、その変数を参照するすべての場所を変更する必要があります。それは心に留めておくべきことです。

于 2009-07-07T21:51:56.207 に答える
0

すべての属性変数に対して余分な作業をすべて行うのは面倒であるという点で、あなたは正しいです。なぜ言語は誰もできないほど基本的なことを許可するのですか?ただし、属性への直接アクセスを許可しないことには、非常に説得力のある理由があります。

私はエッフェルの統一アクセス原則を好みます。属性に割り当てることはできません。属性と関数には同じ方法でアクセスします。

class EXAMPLE
feature
  variable: INTEGER
  variable_function: INTEGER
    do
      result := 4
    end
  variable_two: INTEGER assign variable_assign
  variable_assign (in: INTEGER)
    do
      variable_two := in
    end  
end

feature
test
local
  test: EXAMPLE
  value: INTEGER
do
  create test
  value := test.variable  -- Valid
  value := test.variable_function  -- Valid and same even though it's a function
  test.variable := value -- Invalid
  test.variable_two := value -- Valid, an explicit setter is defined
end
于 2009-07-07T22:06:11.997 に答える
0

ゲッターとセッターを何に使用するかによって異なります。通常、クラスに入力されるデータのサニティ チェックや出力されるデータのフォーマットが必要な場合に使用します。その点で、私はこのクラスとそのデータへのアクセスを必要とする可能性のある他のクラスとの間のインターフェース層としてゲッターとセッターを実際に使用しています。

私は、このクラスにプライベートなデータを処理する方法を知っているように内部コードを書く傾向があるため、独自のゲッターとセッターでデータにアクセスすることは一般的に不要であり、望ましくありません。

ただし、すべてはゲッターとセッターの使用方法に依存します。

于 2009-07-07T21:48:16.993 に答える
0

私の経験則では、値を設定または返すだけでなく、より複雑なことを行う場合は、セッター/ゲッターを使用します。それ以外の場合は、メンバー変数の変更によって発生した問題を修正できるため、必要ありません。

于 2009-07-07T21:49:32.747 に答える
0

これはケースバイケースで考えていく必要があると思います。クラス コード全体で getter を使用すると、コードが複雑になり、おそらく少し遅くなります。ただし、拡張性と再利用性も向上します。

私が通常行っていることは、誰かが私のゲッターを別のものでオーバーライドしたい理由を予測できる場合は、ゲッターを使用することです。それが非常に基本的で単純なもので意味をなさない場合、私は一般的にゲッターを使用しません。

ゲッターなしで変数にアクセスするコードを作成する場合は、ゲッター関数を「最終」にすることを検討してください。そうすれば、誰もあなたのコードを上書きしようとせず、なぜそれが機能しないのかと頭を悩ませることはありません。(Spring および Hibernate プロキシはこれを悪い考えにする可能性があることに注意してください。)

于 2009-07-09T03:26:11.133 に答える
-1

それがアンチパターンであるためには、明らかに有害でなければなりません。ゲッターとセッターを定義する際に、どのように害がある可能性があるのか​​ わかりません。せいぜい、これは時間 (およびタイピング) の無駄であり、意味がありませんが、アンチパターンではありません。

于 2009-07-07T21:44:22.493 に答える