web-dev-qa-db-ja.com

Javaインターフェース使用ガイドライン-インターフェースのゲッターとセッターは悪いですか?

インターフェイスで使用する最良のガイドラインについて人々はどう思いますか?インターフェースには何を入れるべきですか?

原則として、インターフェースは動作を定義するだけで、状態を定義する必要はないと人々が言うのを聞いたことがあります。これは、インターフェイスにゲッターとセッターを含めないことを意味しますか?

私の意見:セッターにはそうではないかもしれませんが、インターフェースに配置するゲッターは有効だと思うことがあります。これは単に、実装クラスにそれらのゲッターを実装するように強制し、クライアントがそれらのゲッターを呼び出して何かを確認できることを示すためです。

35
His

一般的に宣言されているインターフェイスには2つのタイプがあると思います。

  1. a サービスの説明。これはCalculationServiceのようなものです。私はメソッドgetXがこの種のインターフェースにあるべきだとは思わず、確かにsetXではない。それらは実装の詳細を非常に明確に暗示していますが、これはこのタイプのインターフェースの仕事ではありません。
  2. a データモデル-システム内のデータオブジェクトの実装を抽象化するためにのみ存在します。これらは、テストを支援するために、または永続フレームワークを使用して特定のスーパークラスを持つことに(たとえば)切り替えた場合にインターフェースを実装することを選択した(たとえば)の日を覚えている何人かの人々のために使用される可能性があります永続レイヤー)。このタイプのインターフェースでJavaBeanメソッドを使用することは完全に合理的だと思います。

注:コレクションクラスはおそらくタイプ#2に適合します

13
oxbow_lakes

インターフェイスがゲッターとセッターを定義できない理由がわかりません。たとえば、List.size()は実質的にゲッターです。インターフェースはimplementationではなく動作を定義する必要がありますが、handle状態ですが、取得して設定できると主張できます。

たとえば、コレクションインターフェースはすべて状態に関するものですが、コレクションが異なれば、その状態を根本的に異なる方法で格納できます。

編集:コメントは、ゲッターとセッターが単純なフィールドがバッキングストレージに使用されることを意味することを示唆しています。私はこの含意に強く反対します。私の考えでは、値を取得/設定するのは「かなり安い」という意味がありますが、簡単な実装でフィールドとして格納されるわけではありません。


編集:コメントに記載されているように、これは JavaBeans仕様 セクション7.1で明示されています。

したがって、スクリプト作成者がb.Label = fooなどを入力した場合でも、プロパティを設定するためのターゲットオブジェクトへのメソッド呼び出しがあり、ターゲットオブジェクトは完全にプログラムで制御されます。

したがって、プロパティは単純なデータフィールドである必要はなく、実際には計算された値でもかまいません。更新には、プログラムによるさまざまな副作用があります。たとえば、Beanの背景色プロパティを変更すると、Beanが新しい色で再描画される場合があります。」


想定される意味がtrueである場合、プロパティをフィールドとして直接公開することもできます。幸い、その意味は成り立たない:ゲッターとセッターは完全に物事を計算する権利の範囲内にあります。

たとえば、次のコンポーネントについて考えます。

getWidth()
getHeight()
getSize()

そこには3つの変数があるという含意があると思いますか?次のいずれかを持つことは合理的ではありませんか?

private int width;
private int height;

public int getWidth() {
    return width;
}

public int getHeight() {
    return height;
}

public Size getSize() {
    return new Size(width, height); // Assuming an immutable Size type
}

または(できればIMO):

private Size size;

public int getWidth() {
    return size.getWidth();
}

public int getHeight() {
    return size.getHeight();
}

public Size getSize() {
    return size;
}

ここでは、サイズプロパティまたは高さ/幅プロパティのいずれかが便宜上のものですが、それが何らかの理由で無効になるとは思いません。

24
Jon Skeet

ゲッター/セッターには本質的に悪はありません。しかしながら:

  1. オブジェクトを含むフィールドに関して、オブジェクトを(最初のインスタンスで)不変にする傾向があります。どうして ?構築フェーズでほとんどのインスタンスを作成します。後で何かを変更したい場合は、それらの制限を緩和します。したがって、私のインターフェースにはゲッターが含まれる傾向がありますが、セッターは含まれません(他の利点があります-特にスレッド化)。
  2. オブジェクトが私のために何かをして欲しいのですが、逆ではありません。そのため、私のオブジェクトの1つがいくつかのゲッターを取得するとき、他の何かを操作するためにすべてのデータを公開するのではなく、そのオブジェクトに多くの機能を含めるかどうかを尋ね始めます。詳細は this answer を参照してください。

これらはすべてガイドラインです、注意してください。

10
Brian Agnew

一般的に、Beanはその上にインターフェースを持つべきではないと思います。 javabeanは、より一般的な意味でのインターフェースです。インターフェイスは、より複雑なものの外部コントラクトを指定します。 JavaBeanの外部コントラクトとその内部表現は同じです。

ただし、インターフェイスにゲッターがあるべきではないとは言えません。 DataThingieBeanによって実装されるReadableDataThingieインターフェースを持つことは完全に理にかなっています。

4
Kevin Peterson

原則として、インターフェースは動作を定義するだけで、状態を定義する必要はないと人々が言うのを聞いたことがあります。これは、インターフェイスにゲッターとセッターを含めないことを意味しますか?

初心者の場合、少なくともJavaを使用し、例外宣言を除いて、状態なしで完全な動作を定義することはできません。Javaでは、インターフェースは動作を定義しません。インターフェースを定義することはできません。それらが定義するのはタイプです。プロミスです。一連の機能シグネチャを実装する方法について、おそらくいくつかの事後条件に関する例外がありますが、それだけです。動作と状態は、これらのインターフェースを実装するクラスによって定義されます。

次に、ゲッターとセッターがインターフェイスで定義されている場合、それらは完全な動作を実際には定義していません(1つはプロパティに対する読み取り用で、もう1つは書き込み用です)。セッターとゲッターの背後で複雑な動作をすることができますが、それらは可能です実際のクラスでのみ実装されます。 Java言語には、最も制限の多い場合を除いて、インターフェースの動作を自由に定義できる言語はありません。

それを考慮に入れれば、構文的にも意味的にも、インターフェースにセッターとゲッターがあることに問題はありません。

アプリケーションが適切にモデル化されていて、問題がセッターとゲッターを定義するインターフェイスを持っている必要がある場合は、その理由を説明します。たとえば、ServletResponseインターフェースを見てください。

ここで、JavaBeans仕様に準拠したクラスを実装する観点からゲッターとセッターを見る場合、それらのインターフェースを定義する必要はありません。

しかし、Beanのようにセッターとゲッターを必要とし、コンパイルタイプで(Beanのように実行時にではなく)プラグインする必要があり、複数の実装が存在する可能性があるものがある場合は、そうです、これはゲッターとセッターを定義するインターフェースを必要とします。

それが役に立てば幸い。

2
luis.espinal

これは、ゲッター/セッター全体に影響を与える問題であり、このサイトや他の場所で何度も取り上げられています。

私はインターフェースにアクセサを持たない方がいいですが、コンストラクタ引数を使用してコラボレータを実装に追加する傾向があります。

1
Paul McKenzie

何かの単純な実装がゲッターとしてであるという事実は、それが必要な場合にインターフェースにあることを止めるべきではありません。

1
soru

これらの種類のインターフェイスを使用しました。たとえば、beginDate、endDateフィールドを持つクラスがありました。これらのフィールドは多くのクラスにあり、私はさまざまなオブジェクトのそれらの日付を取得する必要がある1つのユースケースを持っていたので、インターフェースを抽出してとても満足していました:)

0
IAdapter

詳細については、「Javaフレームワークアーキテクトの実用的なAPI設計告白(Jaroslav Tulach、2008、Apress)」を参照してください。

0
akarnokd

基本的に、「インスタンスを操作するために、[状態、プロパティ、whateverThignAMaGit]の値を知る必要がありますか?」その後、はい...アクセサはインターフェイスに属しています。

上記のJohnのList.size()は、インターフェースで定義する必要があるゲッターの完璧な例です

0
Newtopian

ゲッターは、オブジェクトの状態を照会するために使用されます-インターフェイスを設計するときに、これを回避できます。読む http://www.pragprog.com/articles/tell-dont-ask

0
TechShan