it-swarm.com.de

Eine Möglichkeit, mehrere Rückgabewerte von einer Methode zurückzugeben: Setzen Sie die Methode in die Klasse, die den Rückgabewert darstellt. Ist es ein gutes Design?

Ich muss 2 Werte von einer Methode zurückgeben. Mein Ansatz ist wie folgt:

  1. erstellen Sie eine innere Klasse mit 2 Feldern, die verwendet werden, um diese 2 Werte beizubehalten
  2. setzen Sie die Methode in diese Klasse ein
  3. instanziieren Sie die Klasse und rufen Sie die Methode auf.

Das einzige, was in der Methode geändert wird, ist, dass am Ende diese beiden Werte den Feldern der Instanz zugewiesen werden. Dann kann ich diese Werte adressieren, indem ich auf die Felder dieses Objekts verweise.

Ist es ein gutes Design und warum?

15
dhblah

Ich würde dies folgendermaßen argumentieren:

  • Warum genau gibt Ihre Methode mehrere Werte zurück? Um welche Art von Zusammenhalt handelt es sich - sollten diese Werte tatsächlich Felder einer einzelnen Klasse sein oder werden sie nur zufällig mit derselben Methode zurückgegeben, aber ansonsten nicht miteinander verbunden? Wenn es das letztere ist, sollten Sie die Methode in zwei Methoden aufteilen. Bearbeiten: Verwenden Sie Ihr Urteil hier; manchmal kann eine Art "zufälliger" Zusammenhalt die beste Option sein. Eine andere Option ist die Verwendung eines Paar- oder Tupelkonstrukts, obwohl diese in OOP normalerweise nicht in öffentlichen APIs angezeigt werden (einige bemerkenswerte Ausnahmen sind Standardsammlungen usw.).
  • Wenn die Werte es verdienen, eine Klasse zu bilden, würde ich wahrscheinlich davon abraten, eine innere Klasse zu verwenden. Innere Klassen werden normalerweise als interne Implementierungsdetails verwendet, die von außen verborgen sind. Gibt es einen Grund, warum dieses Ergebnis keine eigenständige "ausgewachsene" Klasse sein sollte?
  • Welche Operationen gelten für diese neue Klasse, abgesehen vom Speichern von Daten? Beim objektorientierten Design möchten Sie, dass das zugehörige Verhalten nahe an den relevanten Daten liegt (was auch Ihre Absichten zu sein scheinen). Sollte die Methode, auf die Sie sich beziehen, nicht eher in dieser Klasse leben?

Zusammenfassend würde ich sehen, ob ich dieses "Datenobjekt" in eine ausgereifte Klasse mit Daten und Verhalten verwandeln kann. Als zusätzlichen Kommentar möchten Sie möglicherweise die Klasse unveränderlich machen, da ihr Status einmal festgelegt wird. Wenn Sie es unveränderlich machen, können Sie verhindern, dass es falsch festgelegt oder später geändert wird (z. B. wenn jemand eines der Felder auf null setzt und es weitergibt).

Bearbeiten: Wie Patkos Csaba richtig hervorhebt, ist das hier angewandte Prinzip das Prinzip der Einzelverantwortung ( SRP ) - die Klasse, die Sie erstellen möchten, sollte es wirklich haben eine Verantwortung (definiert als Grund für die Änderung ). Diese Entwurfsrichtlinie soll Ihnen helfen, herauszufinden, ob Ihre beiden Felder zu einer einzelnen Klasse gehören oder nicht. Um am Wikipedia-Beispiel festzuhalten, könnte Ihre Klasse als eine Art Bericht angesehen werden. In diesem Fall entspricht sie der SRP, ist jedoch ohne weitere Informationen schwer zu kommentieren.

15
Daniel B

Es gibt das Konzept eines Tupels, das in anderen Sprachen wie Python verfügbar ist.

Man könnte eine Instanz dieser generisierten Klasse zurückgeben, die leicht wiederverwendbar ist:

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

Es scheint, dass diese Klasse einer anderen Klasse die Verantwortung wegnimmt, und das lässt mich denken, dass dieses Design nicht großartig ist.

Für eine Methode, die mehrere Werte zurückgibt, würde ich lieber

  • geben Sie einen generischen Container (z. B. eine Liste oder Karte) zurück, der die Rückgabewerte enthält

oder

  • erstellen Sie eine Klasse für den Rückgabewert, die nur die erforderlichen Felder + Getter + einen Konstruktor mit allen Feldern enthält

Beispiel für die zweite Option:

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

Das Einfügen mehrerer Rückgabewerte von einer Methode in eine eigene Klasse/Struktur wird häufig in nachrichtenbasierten Systemen verwendet, die eine Klasse für Anforderung und Antwort haben. Ein Beispiel hierfür ist Simple Object Access Protocol (SOAP) .

Ist es ein gutes Design und warum?

Zumindest ist es ziemlich häufig. Ob dies gut oder schlecht ist, hängt von Ihrem speziellen Anwendungsfall ab.

1
k3b

Kurze Antwort: Sie können ein Array oder eine Liste mit den beiden Werten zurückgeben.

Ich persönlich würde zwei verschiedene Methoden schreiben, wie

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