1

I have a requirement where in the function takes different parameters and returns unique objects. All these functions perform the same operation.

ie.

public returnObject1 myfunction( paramObject1 a, int a) {
returnObject1 = new returnObject1();
returnObject1.a = paramObject1.a;
return returnObject1;
}

public returnOject2 myfunction( paramObject2 a, int a){
 returnObject2 = new returnObject2();
 returnObject2.a = paramObject2.a;
 return returnObject2;
}

As you can see above, both the function do the same task but they take different parameters as input and return different objects.

I would like to minimize writing different functions that does the same task.

Is it possible to write a generic method for this that can substitute the parameters based on the call to the function?

paramObject and returnObject are basically two classes that have different variables. They are not related to each other.

My objective is that I do not want to do function overloading since the functions do almost the same work. I would like to have a single function that can handle different input and different return output.

my aim is to do something like this (if possible):

public static < E > myfunction( T a, int a ) {
  // do work
}

The return type E and the input T can keep varying.

ajroot
  • 93
  • 1
  • 1
  • 7
  • 1
    Without more specific information on what paramObject1 and paramObject2 are, this is pretty difficult to answer. If they’re similar types, perhaps you should keep the two public methods, move the common code to a new private method, and have each method call that private method. – VGR Jul 06 '17 at 14:25
  • 2
    How are "paramObject" and "returnObject" connected? – Marvin Jul 06 '17 at 14:27
  • Do you mean that the treatment is the same, but with different type of object ? If so, and if they share the same methods name you may be able to write something like `public T myfunction(T param, int a)` – Asew Jul 06 '17 at 14:28
  • Maybe **public Object[] myFunction(int a , Object... abstractObjectArray)** might also sound helpful – ShayHaned Jul 06 '17 at 14:28
  • the question is not phrased correctly and does not provide clarity. do you want multiple methods (overloading) or just a single method processing differently based on paramIObject passed? – digidude Jul 06 '17 at 14:29
  • There's no way to have a single method return different things without having a common interface or abstract class and (probably) declaring a type parameter on either `ReturnObject` or `ParamObject`, the latter of which is highly unlikely to be a good idea here. It's at this point that you should reconsider your design. I only have a pretty vague idea of what you're actually doing but the Abstract Factory pattern seems like it might be useful here. It also may be the case that using overloads as you've already done is a perfectly fine solution. It's difficult to say without knowing more. – Radiodef Jul 06 '17 at 14:48
  • 1
    looks like what @Radiodef says makes sense to me now. I would have to create and interface or abstract class to handle this. – ajroot Jul 06 '17 at 14:54
  • Exactly. Without abstraction, all three actions (`new EitherType()`, `objOfUnrelatedType.a = objOfAnotherUnrelatedType.a;`, `return objOfEitherType;`) of either method *are* different actions, as having similar source code appearance doesn’t count. – Holger Jul 06 '17 at 15:30

2 Answers2

3

you can using the 3rd apply method to remove the code duplications, you separate creation & initialization from the apply method in this approach. and don't care about which type of T is used. for example:

returnObject1 myfunction(paramObject1 a, int b) {
    return apply(returnObject1::new, b, value -> {
        //uses paramObject1
        //populates returnObject1
        //for example:
        value.foo = a.bar;
    });
}

returnOject2 myfunction(paramObject2 a, int b) {
    return apply(returnOject2::new, b, value -> {
        //uses paramObject2 
        //populates returnObject2
        //for example:
        value.key = a.value;
    });
}

<T> T apply(Supplier<T> factory, int b, Consumer<T> initializer) {
    T value = factory.get();
    initializer.accept(value);
    //does work ...
    return value;
}

Note the 2 myfunction is optional, you can remove them from you source code, and call the apply method directly, for example:

paramObject2 a = ...;

returnObject2  result = apply(returnOject2::new, 2, value -> {
    //for example:
    value.key = a.value;
});
holi-java
  • 29,655
  • 7
  • 72
  • 83
  • I would like to eliminate writing two functions. Instead have a single function that takes different parameters. – ajroot Jul 06 '17 at 14:41
  • 2
    @AJRoot maybe apache `beanutils` meet your need. you don't give enough information, so my answer is **abstract** too... :), and notice, the 2 `myfunction` methods above is optional, you can remove them too. – holi-java Jul 06 '17 at 14:43
2

Make interface Foo and implement this interface in both paramObject1 and paramObject2 class. Now your method should be look like:

public Foo myFunction(Foo foo, int a){
    //Rest of the code.
    return foo;
}
  • I was thinking along those lines too and an abstract base class for commonality. – JGFMK Jul 06 '17 at 14:39
  • This makes sense, but I was wondering if there is any other way. I would like to avoid creating a new interface to handle this since I have lots of objects that keep varying. – ajroot Jul 06 '17 at 14:46
  • I think you’re on to something. The challenge is you cannot do `new Foo()` when `Foo` is an interface. Gotta find a solution to that. – Ole V.V. Jul 06 '17 at 14:50