javagenericscode-duplicationdiamond-problemdiamond-operator

Diamond operator extends one or another


In my code I have two classes that are very similar (but still different), yet I want to map them both to a third class. I have it this way:

class AToCMapper {

    public C from(A a) {
        // My mapping code
    }
}
class BToCMapper {

    public C from(B b) {
        // Same mapping code
    }
}

A and B are slightly different, but the code to map to C is identical. To avoid duplication I would like to have something like this:

class CMapper {

    public <T extends A | B> from (T t) {
        // My mapping code
    }
}

Is there a way to do so? Or am I stuck with duplicated code?


Solution

  • Try defining a MappableToC interface that both A and B implement.

    For example:

    interface MappableToC {
      String getLabel();
      Number getData();
    }
    
    class A implements MappableToC {
      String name;
      int value;
    
      public String getLabel() {
        return name;
      }
    
      public Number getData() {
        return value;
      }
    }
    
    class B implements MappableToC {
      String title;
      double amount;
    
      public String getLabel() {
        return title;
      }
    
      public Number getData() {
        return amount;
      }
    }
    
    class C {
      String label;
      Number data;
    }
    
    class CMapper {
      public C map(MappableToC source) {
        C target = new C();
        target.label = source.getLabel();
        target.data = source.getData();
        return target;
      }
    }
    
    public class Main {
      public static void main(String[] args) {
        CMapper mapper = new CMapper();
    
        A aInstance = new A();
        aInstance.name = "Example A";
        aInstance.value = 42;
        C cFromA = mapper.map(aInstance);
        System.out.println(cFromA.label);
        System.out.println(cFromA.data);
    
        B bInstance = new B();
        bInstance.title = "Sample B";
        bInstance.amount = 3.14;
        C cFromB = mapper.map(bInstance);
        System.out.println(cFromB.label);
        System.out.println(cFromB.data);
      }
    }
    

    Output:

    Example A
    42
    Sample B
    3.14
    

    Try on godbolt.org