Java method with variable return type and variable input arguments

I have an abstract Java class "BaseOperation". This class has only one abstract method:

public abstract T execute() { ... return T; } 

BaseOperation subclasses must implement this method:

 public class GetUsersOperation extends BaseOperation<GetUsersResponse> { ... @Override public GetUsersResponse execute() { ... return GetUsersResponse; } } 

This is a great way to put all the usual β€œwork” logic in the BaseOperation class, but still, every particular execute() subclass has a different return type.

Now I need to modify this structure to allow the execute () methods to have a variable number of arguments. For example, for one particular subclass, you would need:

 execute(String, int) 

and the other will need:

 execute(Date, Date, String) 

This is complicated because the execute method is declared in the base class. Just overloading the execution methods in the database is not ideal. Firstly, the amount of congestion will be huge. Secondly, each subclass will use only one of the execution methods, what is the point of all the others?

(in my opinion) the simplest solution would be to declare the execute method with varargs:

 execute(Object... arguments) 

And then empty all the arguments in the subclasses:

 execute(Object... arguments) { String s = (String) arguments[0]; ... } 

Obviously, this has two main disadvantages:

  • Slow performance due to all downcasting operations
  • Calling the execute() methods is no longer strongly typed, because any number of objects can be transmitted without compiler warnings.

Are there templates or other solutions that might not have these flaws?

+6
source share
2 answers

As already mentioned, a general approach to solving your problem is to use bean storage options. But here is another solution based on the construction of the approach:

 public interface BaseOperation<T> { public T execute(); } public class AddOperation implements BaseOperation<Integer> { private int a, b; public void setA(int arg){ a = arg ; return this; } public void setB(int arg){ b = arg; return this; } @Override public Integer execute() { return a+b ; } } 

And then use it like this:

 new AddOperation().setA(1).setB(2).execute(); 

You can mix the necessary and optional parameters as follows:

 public class MultipleAddOperation implements BaseOperation<Integer> { private int sum ; public MultipleAddOperation(int requiredInt){ sum = requiredInt; } public void add(int optionalInt){ sum += optionalInt ; return this; } @Override public Integer execute(){ return sum; } } 

So:

 new MultipleAddOperation(5).add(1).add(2).execute(); 
+2
source

You can use a bean while holding parameters:

 public interface BaseOperation<T, U> { T execute(U input); } public class GetUsersOperation implements BaseOperation<GetUsersResponse, UserInput> { @Override public GetUsersResponse execute(UserInput input) { Date date = input.getDate(); return new GetUsersResponse(date); } } 

There is only one abstract method in your abstract class: it is better to use an interface. You can implement multiple interfaces, while you can extend only one class.

+5
source

Source: https://habr.com/ru/post/981656/


All Articles