42

インターフェイスで使用する最適なガイドラインについて、人々はどう考えていますか? インターフェイスに入るべきものとすべきでないものは何ですか?

一般的なルールとして、インターフェイスは動作のみを定義し、状態を定義する必要はないと人々が言うのを聞いたことがあります。これは、インターフェイスにゲッターとセッターを含めるべきではないということですか?

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

4

11 に答える 11

28

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

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

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


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

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

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


想定される意味正しい場合、プロパティをフィールドとして直接公開することもできます。幸いなことに、その意味は当てはまりません。getter と setter は、物事を計算する権利の範囲内に完全に収まっています。

たとえば、次のコンポーネントを考えてみましょう。

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;
}

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

于 2009-07-15T09:19:11.220 に答える
14

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

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

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

于 2009-07-15T09:58:43.073 に答える
12

ゲッター/セッターには本質的に悪はありません。でも:

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

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

于 2009-07-15T10:08:13.260 に答える
6

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

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

于 2009-07-15T09:19:40.207 に答える
2

一般的なルールとして、インターフェイスは動作のみを定義し、状態を定義する必要はないと人々が言うのを聞いたことがあります。これは、インターフェイスにゲッターとセッターを含めるべきではないということですか?

まず第一に、少なくとも Java では例外宣言を除いて、状態なしで完全な動作を定義することはできません。Java では、インターフェイスは動作を定義しません。彼らはできません。それらが定義するのは型です。おそらくいくつかの事後条件 wrt 例外を伴う機能シグネチャのセットを実装するという約束。しかし、それだけです。動作と状態は、これらのインターフェイスを実装するクラスによって定義されます。

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

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

アプリケーションが適切にモデル化されていて、問題によってセッターとゲッターを定義するインターフェイスが必要な場合は、そうすべきではありません。たとえば、ServletResponse インターフェースを見てください。

さて、JavaBeans 仕様に準拠したクラスを実装するという観点から getter と setter を見ると、それらのインターフェースを定義する必要はありません。

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

それが役に立てば幸い。

于 2010-04-03T22:24:54.340 に答える
1

これは、ゲッター/セッター全体がこのサイトや他の場所で何度も取り上げられている邪悪なトピックに触れています。

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

于 2009-07-15T09:25:10.193 に答える
1

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

于 2009-07-15T10:24:37.470 に答える
1

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

于 2009-07-15T09:32:24.923 に答える
0

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

于 2009-07-15T09:24:46.327 に答える
0

基本的に、「[state, property, whatThignAMaGit] のインスタンスを操作するために、その値を知る必要がありますか?」に対する答えの場合。はい...アクセサはインターフェースに属します。

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

于 2009-07-15T10:26:07.123 に答える
0

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

于 2009-08-16T19:01:13.073 に答える