Home > database >  Refactor similar methods to a generic method in Java
Refactor similar methods to a generic method in Java

Time:12-08

I have three similar classes for different types.

public class IntClass {
    private int p1;  private int p2;
    IntClass(int p1, int p2) { this.p1=p1; this.p2=p2; }
    int getP1() { return p1; }
    int getP2() { return p2; }
}
public class DoubleClass {
    private double p1;  private double p2;
    DoubleClass(double p1, double p2) { this.p1=p1; this.p2=p2; }
    double getP1() { return p1; }
    double getP2() { return p2; }
}
public class StringClass {
    private String p1;  private String p2;
    StringClass(String p1, String p2) { this.p1=p1; this.p2=p2; }
    String getP1() { return p1; }
    String getP2() { return p2; }
}
public class C4 {
    ...
    private IntClass c1;
    private DoubleClass c2;
    private StringClass c3;
    ...
    IntClass getIntClass() { return C1; }
    DoubleClass getDoubleClass() { return C2; }
    StringClass getStringClass() { return C3; }
    ...
}

Somewhere else in codebase, I have following snippet of code with 3 similar methods.

...
int a = getInt(C4::getIntClass, boolValue);
double b = getDouble(C4::getDoubleClass, boolValue);
String c = getString(C4::getStringClass, boolValue);
...
private int getInt(Supplier<IntClass> executable, boolean boolValue) {
    ...
    return boolValue? executable.get().getP1(): executable.get().getP2();
}
private double getDouble(Supplier<DoubleClass> executable, boolean boolValue) {
    ...
    return boolValue? executable.get().getP1(): executable.get().getP2();
}
private String getString(Supplier<StringClass> executable, boolean boolValue) {
    ...
    return boolValue? executable.get().getP1(): executable.get().getP2();
}

I wanted to write a generic method getValue in replacement of getInt,getDouble,getString. How can we do so?

Edit:- Cant make generic Class for IntClass, DoubleClass, StringClass as they serve some other usecase as well and are in different package library. Just wanted to refactor code at my end by writing a common generic method and removing similar redundant code. Just a thought!! Any suggestions specific to usecase would be appreciated.

CodePudding user response:

@Test
  public void test() {
    PairOf<String> pairOfStr = new PairOf<>("abc", "def");
    PairOf<Integer> pairOfInt = new PairOf<>(1, 2);
    PairOf<Double> pairOfDouble = new PairOf<>(1.0, 2.0);
    Assertions.assertEquals(pairOfStr.getFirst(), getValue(pairOfStr, true));
    Assertions.assertEquals(pairOfInt.getFirst(), getValue(pairOfInt, true));
    Assertions.assertEquals(pairOfDouble.getFirst(), getValue(pairOfDouble, true));
  }

  public class PairOf<T> {
    private T first;
    private T second;

    public PairOf(T first, T second) {
      this.first = first;
      this.second = second;
    }

    public T getFirst() {
      return first;
    }

    public T getSecond() {
      return second;
    }

  }

  public <T> T getValue(PairOf<T> t, boolean first) {
    return first ? t.getFirst() : t.getSecond();
  }

With number, you can cast to primitive by method:

getValue(pairOfInt, true).intValue();
    getValue(pairOfDouble, true).doubleValue();

CodePudding user response:

Try this:

public class GenericClass<T> {
    private T p1;
    private T p2;
    GenericClass(T p1, T p2) {
        this.p1=p1;
        this.p2=p2;
    }
    T getP1() { return p1; }
    T getP2() { return p2; }

}
    private T getValue(Supplier<GenericClass<T>> executable, boolean boolValue) {
        return boolValue ? executable.get().getP1(): executable.get().getP2();
    }

CodePudding user response:

Well you need to start with a generic class and do something like:

public class PairOf<T> {
    private T first;
    private T second;

    public PairOf(T first, T second) { 
        this.first = first;
        this.second = second;
    }

    public T getFirst() { return first; }
    public T getSecond() { return second; }

}

Then you can use this class in place of your specific classes exactly as before.

  • Related