Un modo per restituire più valori di ritorno da un metodo: inserire il metodo all'interno della classe che rappresenta il valore di ritorno. È un buon design?

15

Devo restituire 2 valori da un metodo. Il mio approccio è il seguente:

  1. crea una classe interna con 2 campi che verranno utilizzati per mantenere quei 2 valori
  2. metti il metodo all'interno di quella classe
  3. istanzia la classe e chiama il metodo.

L'unica cosa che verrà modificata nel metodo è che alla fine assegnerà quei 2 valori ai campi dell'istanza. Quindi posso indirizzare quei valori facendo riferimento ai campi di quell'oggetto.

È un buon design e perché?

    
posta dhblah 01.10.2012 - 13:52
fonte

5 risposte

15

Lo sosterrò seguendo le seguenti linee:

  • Perché esattamente il tuo metodo restituisce più valori? Di che tipo di coesione stiamo parlando - quei valori dovrebbero essere effettivamente campi di una singola classe, o sono semplicemente restituiti per coincidenza con lo stesso metodo, ma per il resto non correlati? Se è il secondo, dovresti prendere in considerazione la possibilità di dividere il metodo in due metodi, piuttosto. Modifica: usa il tuo giudizio qui; a volte un tipo di coesione "casuale" può essere l'opzione migliore. Un'altra opzione consiste nell'usare un costrutto pair o tuple, sebbene in OOP, queste non sono solitamente viste nelle API pubbliche (alcune eccezioni degne di nota sono collezioni standard, ecc.)
  • Se i valori meritano di formare una classe, probabilmente sconsigliamo di usare una classe interiore. Le classi interne vengono in genere utilizzate come dettagli di implementazione interna, che sono nascoste dall'esterno. C'è qualche ragione per cui questo risultato non dovrebbe essere una classe "in piena regola", a pieno titolo?
  • Oltre a contenere i dati, quali operazioni sono applicabili a questa nuova classe? Nella progettazione orientata agli oggetti, si desidera avere il comportamento correlato vicino ai dati rilevanti (che sembrano essere anche le tue intenzioni). Il metodo a cui ti riferisci di non vivere in questa classe è piuttosto?

Per riassumere, vedrei se posso trasformare questo "oggetto dati" in una classe a tutti gli effetti con dati e comportamento. Come commento aggiuntivo, potresti voler rendere la classe immutabile, dal momento che il suo stato è impostato una volta. Renderlo immutabile ti aiuterà a prevenire che venga impostato in modo errato, o modificato in seguito (ad esempio, qualcuno che imposta uno dei campi su null e lo passi avanti).

Modifica: come correttamente sottolineato da Patkos Csaba, il principio applicato qui è il Principio della singola responsabilità ( SRP ) - la classe che stai cercando di creare dovrebbe avere una sola responsabilità (definita come una ragione per cambiare ). Questa linea guida di progettazione dovrebbe aiutarti a capire se i tuoi due campi appartengono o meno a una singola classe. Per seguire l'esempio di Wikipedia, la tua classe potrebbe essere vista come un tipo di rapporto, nel qual caso è conforme a SRP, ma è difficile commentare senza ulteriori informazioni.

    
risposta data 01.10.2012 - 14:15
fonte
10

Esiste il concetto di una tupla che è presente in altri linguaggi, come Python.

Si potrebbe restituire un'istanza di questa classe generica che è facilmente riutilizzabile:

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;
  }
}
    
risposta data 01.10.2012 - 16:37
fonte
5

Sembra che questa classe stia prendendo le responsabilità da un'altra classe, e questo mi fa pensare che questo design non sia eccezionale.

Per un metodo che restituisce valori multipli, preferirei

  • restituisce un contenitore generico (ad esempio un elenco o una mappa) contenente i valori di ritorno

o

  • crea una classe per il valore di ritorno, che contiene solo i campi necessari + getter + un costruttore con tutti i campi

Esempio per la seconda opzione:

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;
   }
}
    
risposta data 01.10.2012 - 14:14
fonte
1

L'inserimento di più valori di ritorno da un metodo nella propria classe / struttura viene spesso utilizzato nei sistemi basati sui messaggi che avere una lezione per Richiesta e risposta . Un esempio di questo è Simple Object Access Protocol (SOAP) .

Is it a good design and why?

Almeno è abbastanza comune. Se questo è buono o cattivo dipende dal tuo caso speciale.

    
risposta data 01.10.2012 - 17:29
fonte
0

Risposta breve: puoi restituire un array o un elenco con i due valori.

Personalmente scriverò due metodi distinti, come

int x = obj.getX();
int y = obj.getY();
    
risposta data 01.10.2012 - 17:20
fonte

Leggi altre domande sui tag