I have googled this a lot, invalidated the cache, and I can’t seem to find an answer. For background, this is a timetabling system using constraint solving. I have a custom class called Period
with public methods getStart()
and getEnd()
. I also have an abstract class Constraint<V, D>
and a subclass DemAvailConstratint<Demonstrator, Period>
. It is in this subclass (and similarly in another one) where the methods in Period
and Demonstrator
cannot be resolved.
In DemAvailConstraint
the methods showing the error are getStart()
and getEnd()
when called on this.period
but not when called on other Period
objects. Similarly, it happens with isAvailable()
when called on this.getDemonstrator()
in the satisfied()
method. This is a public method in Demonstrator
. Any idea why this would happen?
Here are the classes (with some methods removed for clarity):
public abstract class Constraint<V, D> { private V variable; public Constraint(V variable) { this.variable = variable; } public abstract boolean satisfied(); public abstract int score(); protected V getVariable() { return this.variable; } protected void setVariable(V variable) { this.variable = variable; } }
public class DemAvailConstraint<Demonstrator, Period> extends Constraint { private Period period; private ArrayList<AvailBlock> periodAsBlocks; public DemAvailConstraint(Demonstrator demonstrator, Period period) { super(demonstrator); this.period = period; periodAsBlocks = new ArrayList<>(); periodAsBlocks.add( AvailBlock.from(this.period.getStart()) ); while ( periodAsBlocks.get( periodAsBlocks.size() - 1 ).getEnd().isBefore(this.period.getEnd()) ) { periodAsBlocks.add( AvailBlock.from(periodAsBlocks.get( periodAsBlocks.size() - 1 ).getEnd()) ); } } @Override public boolean satisfied() { // now we check if the demonstrator is available for each block for (AvailBlock block : this.periodAsBlocks) { if ( !this.getDemonstrator().isAvailable(block) ) return false; } return true; } ... public Demonstrator getDemonstrator() { return (Demonstrator) super.getVariable(); } }
public class Period { private String name; private LocalDateTime start; // duration in seconds private int duration; private Lecturer lecturer; private ArrayList<Demonstrator> dems; private ArrayList<Skill> skills; /** * Basic constructor. Use the factory method from() to make a period from AvailBlock objects. * @param name * @param start * @param duration * @param lecturer */ public Period(String name, LocalDateTime start, int duration, Lecturer lecturer) { this.name = name; this.lecturer = lecturer; this.dems = new ArrayList<>(); this.skills = new ArrayList<>(); this.duration = duration; this.start = start; } /** * Static factory method that can create a period from a list of consecutive AvailBlock objects. * @param name * @param blocks * @param lecturer * @return */ public static Period from(String name, List<AvailBlock> blocks, Lecturer lecturer) throws IllegalArgumentException { if ( !AvailBlock.isConsecutive(blocks) ) { throw new IllegalArgumentException( "Non-consecutive AvailBlock objects." ); } ArrayList<AvailBlock> blocksSorted = new ArrayList<>(blocks); Collections.sort(blocksSorted); LocalDateTime start = blocksSorted.get(0).getStart(); int duration = blocksSorted.size(); return new Period(name, start, duration, lecturer); } ... public LocalDateTime getStart() { return start; // more getters and setters ... public LocalDateTime getEnd() { return this.start.plusSeconds(this.duration); } }
Advertisement
Answer
After all sorts of attempts at invalidating the cache, changing the JDK etc., I have deleted the <Demonstrator, Period>
part in the DemAvailConstraint
class declaration. I think I know why this worked. Adding that piece of code made Demonstrator
and Period
into placeholder types rather than referring to my custom classes. This is why the class couldn’t access my methods. I have kept the placeholder code <V, D>
(variable and domain) in the abstract class Constraint
, and I’m now wondering if I actually need to specify those types in the subclass.