How to write Java function that returns values of multiple data types?

后端 未结 11 1565
耶瑟儿~
耶瑟儿~ 2021-01-03 23:34

For example, I want to create a function that can return any number (negative, zero, or positive).

However, based on certain exceptions, I\'d like the function to re

11条回答
  •  悲哀的现实
    2021-01-03 23:59

    IEEE Floating Point

    Most languages will handle your specific example without Exceptions or union types because IEEE floating point includes a representation for NaN. In Java, use Double.NaN:

    public static double quadratic(double a, double b, double c, int polarity) {
        double x = b*b - 4*a*c;
    
        // When x < 0, Math.sqrt(x) retruns NaN
        if (x < 0) {
            return Double.NaN;
        }
        return (-b + Math.sqrt(x) * polarity) / (2*a);
    }
    

    That produces your exact output that you wanted:

    x = 4.0
    x = 3.0
    x = NaN
    x = NaN
    

    Exceptions

    Exceptions are The Old Java Way of solving similar problems:

    public static double quadratic(double a, double b, double c, int polarity) {
        double x = b*b - 4*a*c;
        // When x < 0, Math.sqrt(x) returns NaN
        if (x < 0) {
            throw new Exception("NaN")
        }
        return (-b + Math.sqrt(x) * polarity) / (2*a);
    }
    

    Here's your client code for an Exception.

    a=1; b=-7; c=12;
    
    // x = 4.0
    try {
        System.out.println("x = " + quadratic(a, b, c, 1));
    } catch (Exception iae) {
        System.out.println("Oopsie: " + iae.getMessage());
    }
    
    // x = 3.0
    try {
        System.out.println("x = " + quadratic(a, b, c, -1));
    } catch (Exception iae) {
        System.out.println("Oopsie: " + iae.getMessage());
    }
    
    // "invalid" coefficients.
    a=4; b=4; c=16;
    
    // Oopsie: NaN
    try {
        System.out.println("x = " + quadratic(a, b, c, 1));
    } catch (Exception iae) {
        System.out.println("Oopsie: " + iae.getMessage());
    }
    
    // Oopsie: NaN
    try {
        System.out.println("x = " + quadratic(a, b, c, -1));
    } catch (Exception iae) {
        System.out.println("Oopsie: " + iae.getMessage());
    }
    

    Union Types

    To truly pass or return unrelated types to or from a method, you want Union types which Java does not really support. But Paguro provides Union Types which you can use in Java like this (using Or):

    public static Or quadratic(double a, double b,
                                              double c, int polarity) {
        double x = b*b - 4*a*c;
    
        // When x < 0, Math.sqrt(x) retruns NaN
        if (x < 0) {
            return Or.bad("NaN");
        }
        return Or.good((-b + Math.sqrt(x) * polarity) / (2*a));
    }
    
    @Test public void testQuadradic() {
        double a, b, c;
        a=1; b=-7; c=12;
    
        // x = Good(4.0)
        System.out.println("x = " + quadratic(a, b, c, 1));
    
        // x = 3.0
        System.out.println(
                (String) quadratic(a, b, c, -1)
                        .match(good -> "x = " + good,
                               bad -> "Oopsie: " + bad));
    
        // "invalid" coefficients.
        a=4; b=4; c=16;
    
        // x = Bad("NaN")
        System.out.println("x = " + quadratic(a, b, c, 1));
    
        // Oopsie: NaN
        System.out.println(
                (String) quadratic(a, b, c, -1)
                        .match(good -> "x = " + good,
                               bad -> "Oopsie: " + bad));
    }
    

    Conclusion

    For your specific example, just use Floating Point. For a more general solution, I find union types more useful than Exceptions. You can use union types as arguments to a method that might take two different inputs which have no common interface or ancestor. They are also more friendly to Functional Programming.

提交回复
热议问题