In Java, how can I return two different types based on an argument?

Matthew Gaiser :

Say that I have a method like this:

public AbstractContractApplication acceptOffer(AcceptedOfferDto dto)
{
    // various application stuff
    Contract contract; // deeply integrated into the above code
    return processedApplication;  // also deeply integrated into the above code 
}

I would like to refactor my method to sometimes return contract instead of processedApplication based on an argument provided in the AcceptedOfferDto. Ideally something like this:

if (AcceptedOfferDto.getReturnConfig() == 1){
return contract;
}

else {
return processedApplication; 
}

Is there a clean way to do this which does not involve copy and pasting the bulk of the code in the function or refactoring a large block of extremely important business logic?

The current line of thinking is to create a class that contains instances of both objects and just select the correct value from that. What other options might be available?

Victor Stafusa :

Supposing that Contract and AbstractContractApplication have nothing useful in common to rely on polimorphism and you can't refactor too much things, you could use this:

public interface EitherOne<A, B> {
    public default boolean isA() { return false; }
    public default boolean isB() { return false; }
    public default A getA() { throw new IllegalStateException(); }
    public default B getB() { throw new IllegalStateException(); }

    public static <A, B> EitherOne<A, B> a(A a) {
        return new EitherOne<>() {
            @Override public boolean isA() { return true; }
            @Override public boolean getA() { return a; }
        };
    }

    public static <A, B> EitherOne<A, B> b(B b) {
        return new EitherOne<>() {
            @Override public boolean isB() { return true; }
            @Override public boolean getB() { return b; }
        };
    }
}

I really don't recomend anyone using this. It should be used only as a quick and dirty escape hatch hack for complicated situations.

Then, you can try this:

public EitherOne<Contract, AbstractContractApplication> acceptOffer(AcceptedOfferDto dto) {
    // various application stuff
    AbstractContractApplication processedApplication = ...;
    Contract contract = ...; // deeply integrated into the above code
    if (AcceptedOfferDto.getReturnConfig() == 1) return EitherOne.a(contract);
    return EitherOne.b(processedApplication);  // also deeply integrated into the above code 
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=23181&siteId=1