Search code examples
javasubclassingabstract-factory

How do I use subclasses in a factory subclass to override abstract class in a superclass factory?


I am writing a program that needs to do CRUD operations with sub-classes of an abstract object Assignment. I have factories to do the CRUD operations, but I am having a problem overriding the methods.

public abstract class Assignment {
    protected Integer id = null;
    protected String name = null;
    public Assignment() {}
    public Assignment(Assignment original) { // code here to clone }
    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

a concrete assignment

public class DCONAssignment extends Assignment {
    protected Integer amount = null;
    protected String type = null;
    public DCONAssignment() {}
    public DCONAssignment(DCONAssignment original) { // code here to clone }
    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

abstract factory

public abstract class AssignmentProcessor {
    public abstract Assignment loadAssignment(Integer assignmentId);
//  public abstract boolean saveAssignment(Assignment assignment); // option 1
//  public abstract boolean saveAssignment(<? extends Assignment> assignment); // option 2 // This says "abstract methods do not specify a body"
//  public <T extends Assignment> boolean saveAssignment(T assignment) { //option 3
    public boolean saveAssignment(Assignment assignment) { //option 4
        return false;
    }
    protected Assignment loadAssignment(Integer assignmentId, Class<? extends Assignment> clazz) {
        Assignment assignment = null;
        try {
            assignment = clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        BurstAssignment burstAssignment = null; // load assignmnet from db
        assignment.setId(burstAssignment.getId());

        return assignment;
    }
}

and concrete factory

public class DCONAssignmentProcessor extends AssignmentProcessor {
    @Override
    public DCONAssignment loadAssignment(Integer assignmentId) {
        DCONAssignment assignment = (DCONAssignment) loadAssignment(assignmentId, DCONAssignment.class);
        return assignment;
    }
    @Override
    public boolean saveAssignment(DCONAssignment assignment) { // eclipse says I need to override a method with options 1, 3 and 4
        return false;
    }
}

In conclusion, the abstract factory handles some of the heavy lifting for loading an Assignment. The concrete factories handle details for their particular implementation of the Assignment class. The problem is overriding the abstract methods with concrete parameters. So the question is, how can I specify a method in the abstract factory and override it with a concrete parameter in the concrete factory?


Solution

  • I solved the problem the solution was to make the abstract factory generic

    public abstract class AssignmentProcessor<T extends Assignment>  {
        public abstract T loadAssignment(Integer assignmentId);
        public boolean saveAssignment(T assignment) {
            return false;
        }
        protected Assignment loadAssignment(Integer assignmentId, Class<T> clazz) {
            Assignment assignment = null;
            try {
                assignment = clazz.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            BurstAssignment burstAssignment = SessionHelper.getSession().getBurstAssignment(assignmentId);
            assignment.setId(burstAssignment.getId());
            return assignment;
        }
    }
    

    concrete factory

    public class DarfAssignmentProcessor extends AssignmentProcessor<DarfAssignment> {
        @Override
        public DarfAssignment loadAssignment(Integer assignmentId) {
            DarfAssignment assignment = (DarfAssignment) loadAssignment(assignmentId, DarfAssignment.class);
            return assignment;
        }
        @Override
        public boolean saveAssignment(DarfAssignment assignment) {
            return false;
        }
    }