web-dev-qa-db-fra.com

Une façon de renvoyer plusieurs valeurs de retour à partir d'une méthode: mettez la méthode dans la classe représentant la valeur de retour. Est-ce un bon design?

J'ai besoin de renvoyer 2 valeurs d'une méthode. Mon approche est la suivante:

  1. créer une classe interne avec 2 champs qui seront utilisés pour conserver ces 2 valeurs
  2. mettre la méthode à l'intérieur de cette classe
  3. instancier la classe et appeler la méthode.

La seule chose qui sera modifiée dans la méthode est qu'à la fin il assignera ces 2 valeurs aux champs de l'instance. Ensuite, je peux aborder ces valeurs en faisant référence aux champs de cet objet.

Est-ce un bon design et pourquoi?

15
dhblah

Je dirais cela selon les lignes suivantes:

  • Pourquoi exactement votre méthode renvoie-t-elle plusieurs valeurs? De quel type de cohésion parlons-nous - ces valeurs devraient-elles en fait être des champs sur une seule classe, ou sont-elles simplement renvoyées par coïncidence par la même méthode, mais autrement sans rapport? Si c'est le dernier, vous voudrez peut-être plutôt envisager de diviser la méthode en deux méthodes. Edit: utilisez votre jugement ici; parfois, un type de cohésion "fortuite" peut être la meilleure option. Une autre option consiste à utiliser une construction paire ou Tuple, bien que dans la POO, ceux-ci ne sont généralement pas vus dans les API publiques (certaines exceptions notables étant les collections standard, etc.).
  • Si les valeurs méritent de former une classe, je déconseillerais probablement d'utiliser une classe interne. Les classes internes sont généralement utilisées comme détails d'implémentation internes, qui sont cachés de l'extérieur. Y a-t-il une raison pour laquelle ce résultat ne devrait pas être une classe à part entière, à part entière?
  • Outre la détention de données, quelles opérations sont applicables à cette nouvelle classe? Dans la conception orientée objet, vous souhaitez que le comportement associé soit proche des données pertinentes (qui semblent également être vos intentions). La méthode à laquelle vous faites référence ne devrait-elle pas plutôt vivre dans cette classe?

Pour résumer, je verrais si je peux transformer cet "objet de données" en une classe à part entière avec à la fois des données et un comportement. Comme commentaire supplémentaire, vous souhaiterez peut-être rendre la classe immuable, car son état est défini une fois. Le rendre immuable aidera à éviter qu'il ne soit mal défini ou modifié ultérieurement (par exemple, quelqu'un définissant l'un des champs sur null et le transmettant).

Edit: Comme Patkos Csaba le souligne correctement, le principe appliqué ici est le principe de responsabilité unique ( SRP ) - la classe que vous essayez de créer devrait vraiment avoir une responsabilité (définie comme une raison de changement ). Cette directive de conception devrait vous aider à déterminer si vos deux champs appartiennent ou non à une seule classe. Pour s'en tenir à l'exemple de Wikipédia, votre classe pourrait être considérée comme un type de rapport, auquel cas il est conforme à SRP, mais il est difficile de commenter sans plus d'informations.

15
Daniel B

Il y a le concept d'un Tuple qui est présenté dans d'autres langages, comme Python.

On pourrait retourner une instance de cette classe générique qui est facilement réutilisable:

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

Il semble que cette classe enlève des responsabilités à une autre classe, et cela me fait penser que ce design n'est pas génial.

Pour une méthode qui renvoie des valeurs multibles, je préfère

  • retourner un conteneur générique (par exemple une liste ou une carte) contenant les valeurs de retour

ou

  • créer une classe pour la valeur de retour, qui contient uniquement les champs nécessaires + les getters + un constructeur avec tous les champs

Exemple pour la deuxième 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

Placer plusieurs valeurs de retour d'une méthode dans sa propre classe/structure est souvent utilisé dans systèmes basés sur les messages qui ont une classe pour Demande et réponse . Un exemple de ceci est Simple Object Access Protocol (SOAP) .

Est-ce un bon design et pourquoi?

Au moins, c'est assez courant. Si c'est bon ou mauvais dépend de votre cas d'utilisation spécial.

1
k3b

Réponse courte: vous pouvez renvoyer un tableau ou une liste avec les deux valeurs.

Personnellement, j'écrirais deux méthodes distinctes, comme

int x = obj.getX();
int y = obj.getY();
0
Tulains Córdova