简体   繁体   中英

Java how to implement interface with a variadic method and generic return type

I am trying to implement a UI where in the user will type a value into the console and my program is supposed to call a function which will either just execute and modify some value or execute and return something. In either case, this function could take parameters or not.

So at this point this is basically sounding like getters and setters, but I don't want to fully implement it in that fashion and this is to avoid having to go through 10+ if statements to determine what to do for any given user input.

So my solution is to create a sort of interface like this inside my class and for each activity I want to run, I create an instance of it using this interface:

private interface DoActivity <R> {
    public R execute(Object... param);
}

This works for when I don't want to specify the types of the parameters to pass to the execute method, but when I create an instance of DoActivity like this with it's execute method:

private class setPerson implements DoActivity {
    @Override
    public Void execute(String name, String telephone) {
        ...
        return null;
    }
}

I get an error with the above: method does not implement or override a method from supertype Is there a way to do what I want without resorting to reflection?

Sample use:

// at prompt
>> Enter an operation: 1 Bumble Bee
>> ...

// In program
String input = "1 Bumble Bee";
String split[] = input.split();
int operation = Integer.parseInt(split[0]);
DoActivityArray[operation - 1].execute(split[1], split[2]);

The solution, for your particular example, is actually quite easy:

private class setPerson implements DoActivity{
    @Override
    public Object execute(final Object ...params){
        if(params.length != 2)
            throw new RuntimeException(
                "setPerson must take an array of exactly two strings");
        try{
            final String name = (String)params[0];
            final String telephone = (String)params[1];
            ...
            return null;
        } catch(ClassCastException cce){
            throw new RuntimeException(
                "setPerson must take an array of exactly two strings");
        }
    }
}

Well, the error is sensible. The interface says the execute method can take a arbitrary number of Object arguments but the attempt at an implementation only actually implements the one variant that takes exactly two arguments (Strings, specifically). All of the other variants (exactly one argument, or three arguments, and so on) are not implemented.

In terms of avoiding a big if/else, how about adding a canExecute method that returns a boolean. Create a list of potential DoActivity implementations, find the first one in the list that returns true for canExecute , and then execute its execute method, which presumes the type and number of arguments.

interface DoActivity<R> {

    public boolean canExecute(Object... param);

    public R execute(Object... param);
}

class SetPerson implements DoActivity {

    @Override
    public Void execute(Object... param) {
        String name = (String)param[0];
        String telephone = (String)param[1];        
        ...
    }

    @Override
    public boolean canExecute(Object... param) {
        return param != null && param.length == 2;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM