Search code examples
javaabstract-classgeneric-programming

How to specify the return type of the method of an abstract class


I found a lot of post on the subject, but couldn't manage to find the solution I was looking for.

So here is the deal:

I have a first abstract class with two subclasses:

public abstract class A {
  public A(args){..}
}
public class B extends A {
  public B(args){
    super(args);
  }
}
public class C extends A{
  public C(args){
    super(args);
  }
}

args is some variables but doesn't change in form. Some other stuff are in the classes, but it doesn't matter here.

Now, I have another abstract class with two subclasses that are builders for B and C. The most part of the builders is the same, so I'd like it to be in the abstract builder

public abstract class Builder {
  public A build(*?*){
    //compute args
    return new *either B or C*(args);
  }
}
public class B_Builder extends Builder {
  public B build(*?*){
    super(*?*);
  }
}
public class C_Builder extends Builder{
  public C build(*?*){
    super(*?*);
  }
}

Once again, the other stuff in the builders doesn't really matter.

My question is how to tell to the Builder abastract class what the return type of build should be through the builders subclass. Knowing that the return type B and C both extends A. I guess I should use some generic stuff, but I can't manage to make it work.

Can anyone help me ?

Thanks a lot !

LD


Solution

  • You can do it with a generic type parameter and an abstract creator method that does the construction while the abstract class does the heavy lifting:

    public abstract class Builder<T extends A> {
      public T build(*?*){
        //compute args
        return create(args);
      }
    
      protected abstract T create(args);
    }
    
    public class B_Builder extends Builder<B> {
      @Override
      protected B create(args) {
        return new B(args);
      }
    }
    
    public class C_Builder extends Builder<C>{
      @Override
      protected C create(args) {
        return new C(args);
      }
    }