5

このクラスを例に取りましょう:

public class Student{
    private String name;
    private String id;

    public Student(String name, String id){
        this.name = name;
        this.id = id;
    }

    ... getters and setters for both fields

これと比較してください:

public class Student{
    public final String name;
    public final String id;

    public Student(String name, String id){
        this.name = name;
        this.id = id;
    }
 }

私の意見では、アクセサーは必要ありません。
これは悪い OO 設計と見なされますか?

4

8 に答える 8

7

これは負荷の高い質問です。

残念ながら、良い (または悪い) デザインは、その使用方法に 100% 依存しています。

経験則として、オブジェクト モデルがアクセスを制御できるように、メンバー変数を非公開にしておくことをお勧めします。これは、最初のアプローチの方が優れていることを意味します。

しかし

値が決して変わらない場合、ポイントは何ですか? セッターが決して使用されないのに、なぜわざわざセッターを書くのでしょうか?

それで、どちらが良いですか?上で述べたように、それはあなたがこれを何のために行っているかによって異なります。授業の課題であれば、最初のものを使います。それはより「教科書」であるため、先生はそれをより気に入るはずです。

したがって、これが個人的なプロジェクトであるか、将来のリリースを利用できる仕事である場合、私は 2 つの間のクロスを使用します。

public class Student{
    private final String name;
    private final String id;

    public Student(String name, String id){
        this.name = name;
        this.id = id;
    }

  ... getters ONLY for both fields

メンバー フィールドは非公開であり、未使用のメソッドの「コードの匂い」がないため、このアプローチは安全です。要件が変更されてフィールドを変更する必要がある場合でも、セッターを非常に簡単に追加できるため、これはかなり拡張可能です。

于 2012-08-08T00:14:59.773 に答える
6

可変性とスコープを厳密に最小限に制限することを常に目指すべきです。あなたの場合:フィールドをプライベート、ファイナル、ゲッターあり、セッターなしにします。

おまけ: クラスは不変になり、スレッドセーフになります。

この投稿も参照してください。

于 2012-08-08T00:19:05.330 に答える
2

Getter と Setter は API をより安定させます。たとえば、他のクラスからアクセスされるクラス内のフィールド public を考えてみましょう。後で、変数を取得および設定する際に、追加のロジックを追加する必要があります。これは、API を使用する既存のクライアントに影響します。したがって、この public フィールドを変更すると、それを参照する各クラスを変更する必要があります。反対に、アクセサー メソッドを使用すると、一部のデータをキャッシュし、後で遅延して初期化するなどのロジックを簡単に追加できます。さらに、新しい値が以前の値と異なる場合は、プロパティ変更イベントを発生させることができます。これはすべて、アクセサー メソッドを使用して値を取得するクラスに対してシームレスになります。

ThePragmaticProgrammer は、ゲッターとセッターも常に使用することを推奨しています。これは、より一般的なインターフェイスであるためです。この記事http://c2.com/cgi/wiki?AccessorsAreEvilを確認してください。これは非常に優れており、なぜそれらを使用する必要があるかについて深く理解できます。

于 2012-08-08T02:30:21.200 に答える
0

整合性ルール。変数へのパブリックアクセスを備えたクラス/プロパティがあり、他のクラス/プロパティには「ゲッター」がある場合、それは良い場所にはなりません。

クラスを受講してフィールドStudentを追加するとしjava.util.Dateます。

public final Date dateOfBirth;

ああ、今あなたStudentは制御されていない方法で変更可能です。必要です。

private final Date dateOfBirth;
...
public Date dateOfBirth() {
     return new Date(dateOfBirth.getTime()); // Awful API.
}

一般に、すべての(インスタンス)フィールドをプライベートにします(データ転送オブジェクトを除く)。あなたがセッターを持っているなら、あなたはおそらくカプセル化へのすべての希望を放棄しているでしょう。ゲッターは不変の値オブジェクトに適しています。(「get」プレフィックスは(ほとんど)Javaの規則ですが、特に不変の値オブジェクトとtell-don't-askインターフェイスを優先するコードでは、大部分がノイズになります。「get」を削除すると、クライアントコードには直接フィールドアクセスに対する冗長性としての余分な「()」。)

于 2012-08-08T02:48:18.490 に答える
0

そこにはいくつかの良い答えがあり、必要に応じて可変性を制限するために、フィールドをプライベートにし、適切なコンストラクター/ゲッター/セッターを追加することに同意します。

フィールドベースの割り当てを使用することの別の欠点を指摘します。プロキシ ベースの AOP は、フィールド割り当てにポイントカットを追加するのに問題があるため、プロキシ ベースの AOP コンストラクトを介してログ (およびその他の操作) を実行することは困難になります。実際に織ることを余儀なくされる可能性が最も高く、それはより複雑になります. Spring 自身のドキュメントから:

Spring AOP は現在、メソッド実行のジョイン ポイントのみをサポートしています (Spring Bean でのメソッドの実行をアドバイスします)。フィールド インターセプトは実装されていませんが、コア Spring AOP API を壊すことなくフィールド インターセプトのサポートを追加できます。フィールドへのアクセスを通知し、参加ポイントを更新する必要がある場合は、AspectJ などの言語を検討してください。

于 2012-08-08T04:29:32.357 に答える
0

フィールドが の場合、finalゲッター/セッターを使用する必要はありません。セッターも変更されないため意味がありません。

于 2012-08-08T00:13:16.960 に答える
-1

これは悪い考えではないと思います。

それらが変更されない場合は、適切なキーワードでフィールドをマークしてくださいFinal

また、不変の値を別の方法で表示することもお勧めします。たとえば、Java の定数は通常、すべて大文字で表されます。

于 2012-08-08T00:18:14.640 に答える