2016-06-23 18 views
6

In una delle mie classi Java ho queste 2 funzioni molto simili. C'è un modo in Java per combinarli in un'unica funzione, quindi non devo mantenere 2 funzioni?Come combinare funzioni Java simili in una (In C++ userei i modelli)

public static boolean areValuesValid(double [] values, int numElements) { 
    if(values == null || values.length != numElements) { 
     return false; 
    } 
    for(int i = 0; i < numElements; ++i) { 
     if(Double.isNaN(values[i])) { 
      return false; 
     } 
    } 
    return true; 
} 

public static boolean areValuesValid(float [] values, int numElements) { 
    if(values == null || values.length != numElements) { 
     return false; 
    } 
    for(int i = 0; i < numElements; ++i) { 
     if(Float.isNaN(values[i])) { 
      return false; 
     } 
    } 
    return true; 
} 
+0

Considerare l'utilizzo di un generatore di codice, ad es. https://github.com/square/javapoet – midor

+0

Si noti che C++ non combina le funzioni simili in uno utilizzando i modelli; i modelli generano una nuova funzione per ogni tipo diverso. –

+0

@Luovo Bloch, sì è vero, ma io c + h ho solo bisogno di mantenere una funzione modello nel mio codice sorgente piuttosto che due. –

risposta

4

Non è uno scenario ideale, per le ragioni spiegate da @ericbn. Ma ecco un modo per evitare la maggior parte della duplicazione utilizzando un lambda:

public static boolean areValuesValid(double [] values, int numElements) { 
    return areValuesValid(values, numElements, i -> !Double.isNaN(values[i])); 
} 

public static boolean areValuesValid(float[] values, int numElements) { 
    return areValuesValid(values, numElements, i -> !Float.isNaN(values[i])); 
} 

private static boolean areValuesValid(Object values, int numElements, IntPredicate tester) { 
    if(values == null || Array.getLength(values) != numElements) { 
     return false; 
    } 
    for(int i = 0; i < numElements; ++i) { 
     if(!tester.test(i)) { 
      return false; 
     } 
    } 
    return true; 
} 
+0

Grazie mille! È necessaria solo una piccola correzione logica all'interno del ciclo. L'if-statement non dovrebbe essere negato. –

+0

@ MarekKnows.com Risolto, grazie. – shmosel

5

La tua domanda è difficile in un certo senso per Java:

  1. double e float sono tipi primitivi, e come tali non sono parte di una gerarchia di classi. L'involucro Double e Float classi estende Number, che si estende Object, ma
  2. Un array di tipi primitivi non è la stessa di un array di oggetti, e Java non AUTOBOX un float[] a Float[], per esempio.
  3. Non esiste il metodo isNan(Number n) o isNan(Object o) nell'API Java, ma quelli precedenti che è stato utilizzato, che prevedono un double o un float. Tuttavia, è possibile eseguire Double.isNan(n.doubleValue()) per qualsiasi Number n.

TL; DR In Java la pratica comune per i tipi primitivi è quello di avere implementazioni separate per ciascuno di loro, come hai fatto tu.

EDIT: Come @azurefrog suggerito:

public static boolean areValuesValid(Number[] values, int numElements) { 
    if (values == null || values.length != numElements) { 
     return false; 
    } 
    for (Number value : values) { 
     if (Double.isNaN(value.doubleValue())) { 
      return false; 
     } 
    } 
    return true; 
} 

E poi dovresti usare Apache Commons ArrayUtils:

public static boolean areValuesValid(double[] values, int numElements) { 
    return areValuesValid(ArrayUtils.toObject(values), numElements); 
} 

public static boolean areValuesValid(float[] values, int numElements) { 
    return areValuesValid(ArrayUtils.toObject(values), numElements); 
} 

EDIT2: @ soluzione shmosel passa l'array come un Object e da qui evita la conversione dell'intero array in un tipo in scatola. Una soluzione che vale la pena considerare per evitare questo sovraccarico.

+0

Per quanto riguarda il terzo punto, esiste un metodo 'Number # doubleValue()', quindi puoi semplicemente estrarre il doppio da qualsiasi 'Numero' e chiamare' Double.isNaN() 'su quello. – azurefrog

+0

Per quanto riguarda il secondo punto, apache [ha una classe ArrayUtils] (http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/ArrayUtils.html#toObject (double [])) che fornirà automaticamente gli array di primitivi per te, se sei disposto a inserire librerie di terze parti. – azurefrog

-3

Per semplificare le cose, vorrei utilizzare istanza di:

public static boolean areValuesValid(Object[] values) { 
    if (values == null) { 
     return false; 
    } 
    for(int i = 0; i < values.length; ++i) { 
     //if not Float and not Double return false 
     if (values[i] instanceof Float || values[i] instanceof Double) { 
      return true; 
     } 
    } 
    return false; 
} 

non sono sicuro se proprio deve passare nelle numElements.

+0

'float []' non è una sottoclasse di 'Object []'. – shmosel

+0

Stai verificando diversi criteri di convalida rispetto all'OP, che sta verificando per vedere se la lunghezza dell'array è come previsto e se contiene valori non numerici. – azurefrog