web-dev-qa-db-ja.com

メソッドから複数の戻り値を返す方法:戻り値を表すクラス内にメソッドを置きます。それは良いデザインですか?

メソッドから2つの値を返す必要があります。私のアプローチは次のとおりです:

  1. これらの2つの値を保持するために使用される2つのフィールドを持つ内部クラスを作成します
  2. そのクラス内にメソッドを置く
  3. クラスをインスタンス化し、メソッドを呼び出します。

メソッドで変更される唯一のことは、最後にそれらの2つの値をインスタンスのフィールドに割り当てることです。次に、そのオブジェクトのフィールドを参照することで、これらの値に対処できます。

それは良いデザインですか、なぜですか?

15
dhblah

私はこれを次のように主張します:

  • メソッドが複数の値を正確に返すのはなぜですか?どのような種類のまとまりについて話しているのですか?それらの値は実際には単一のクラスのフィールドである必要がありますか、それとも同じメソッドによって偶然に返されただけで、それ以外は無関係ですか?後者の場合は、メソッドを2つのメソッドに分割することを検討してください。編集:ここであなたの判断を使用してください。ある種の「偶然」の凝集が最良のオプションである場合があります。もう1つのオプションは、ペアまたはタプル構成を使用することですが、OOPではこれらは通常、パブリックAPIでは見られません(いくつかの注目すべき例外は標準コレクションなどです)。
  • 値がクラスを形成するに値する場合、おそらく内部クラスを使用しないことをお勧めします。内部クラスは通常、内部実装の詳細として使用され、外部からは隠されています。この結果自体が「本格的な」クラスにならない理由はありますか?
  • データを保持する以外に、この新しいクラスに適用できる操作は何ですか?オブジェクト指向の設計では、関連する動作を関連するデータに近いものにする必要があります(これも意図されているようです)。あなたが参照しているメソッドは、このクラスではなく生きるべきですか?

要約すると、この「データオブジェクト」を、データと動作の両方を備えた本格的なクラスに変換できるかどうかを確認します。追加のコメントとして、状態が一度設定されるので、クラスを不変にすることができます。不変にすると、誤って設定されたり、後で変更されたりするのを防ぐのに役立ちます(たとえば、誰かがフィールドの1つをnullに設定して渡す)。

編集:Patkos Csabaが正しく指摘しているように、ここで適用されている原則は単一責任原則( [〜#〜] srp [〜#〜] )です-作成しようとしているクラスは実際に1つの責任(変更の理由として定義)。この設計ガイドラインは、2つのフィールドが1つのクラスに属しているかどうかを理解するのに役立ちます。ウィキペディアの例に固執するために、クラスはレポートの一種と見なすことができます。その場合、クラスはSRPに準拠していますが、それ以上の情報なしにコメントすることは困難です。

15
Daniel B

Pythonなどの他の言語で採用されているタプルの概念があります。

簡単に再利用できるこの汎用クラスのインスタンスを返すことができます。

public class TypedTuple<L, R> implements Serializable {
private static final long serialVersionUID = 1L;

  protected L left;
  protected R right;

  protected TypedTuple() {
    // Default constructor for serialization
  }

  public TypedTuple(L inLeft, R inRight) {
    left = inLeft;
    right = inRight;
  }

  public L getLeft() {
    return left;
  }

  public R getRight() {
    return right;
  }
}
10
Cuga

このクラスは他のクラスから責任を奪っているようで、これはこのデザインは素晴らしいとは思えません。

Multible値を返すメソッドの場合は、むしろ

  • 戻り値を含む一般的なコンテナ(リストやマップなど)を返します

または

  • 戻り値のクラスを作成します。これには、必要なフィールド+ゲッター+すべてのフィールドを持つコンストラクタが含まれます

2番目のオプションの例:

public Class FooBarRetval {
   private String foo;
   private int bar;

   public FooBarRetval (String foo, int bar) {
      this.foo = foo;
      this.bar = bar;
   }

   public String getFoo() {
      return foo;
   }

   public int getBar() {
      return bar;
   }
}
5
user281377

メソッドからの複数の戻り値を独自のクラス/構造に配置することは、多くの場合 メッセージベースのシステム で使用されます 要求と応答 に対して1つのクラスがあります。この例は Simple Object Access Protocol(SOAP) です。

それは良いデザインですか?なぜですか?

少なくともそれはかなり一般的です。これが良いか悪いかはあなたの特別なユースケースに依存します。

1
k3b

短い答え:2つの値を持つ配列またはリストを返すことができます。

私は個人的に次のような2つの異なる方法を記述します

int x = obj.getX();
int y = obj.getY();
0