-
Notifications
You must be signed in to change notification settings - Fork 54
Dealing with wildcards
LearnLib and AutomataLib, which LearnLib is based on, make heavy use of Java Generics. This is done to ensure that interface contracts can capture common usage patterns across a wide range of specific data structures (such as various different automata models or input and output symbols).
For instance, DFAs are defined in AutomataLib as DFA<S,I>, where S denotes the class used for representing states and I denotes the class of input symbols the DFA operates on.
There are several DFA implementations available in AutomataLib, with specialized classes that represent states. Implementors of learning algorithms are free to utilize any automaton implementation they deem fit for the task, which means that arbitrary state classes may be used.
To shield the user from the specifics of the chosen automata implementation, learning algorithms for DFAs will thus return models as DFA<?,I>, i.e., the class variable for states is kept unbound. This at first seem to present an obstacle when actually working with the returned DFA data structure, as, e.g., retrieving state objects from the structure is not directly possible, as "?" is merely a wildcard and not a valid data type.
To process DFA instances with unbound type variables it is thus recommended to bind those in the scope of private methods. The following code demonstrates this:
public boolean hasEvenNumberAcceptingStates(DFA<?,I> dfa) {
int count = countAcceptingStates(dfa);
return (count % 2 == 0);
}
private <S> int countAcceptingStates(DFA<S,I> dfa) {
int count = 0;
for(S state : dfa.getStates()) {
count += dfa.isAccepting(state) ? 1 : 0;
}
return count;
}
The method hasEvenNumberAcceptingStates is given a DFA instance with one unbound type variable. To be able to iterate over the states of the automaton, a private method is declared (countAcceptingStates) which binds the type variable. Thus it now is easily possible to operate on the DFA structure without being exposed to the internal implementation details of the concrete DFA instance.
This mechanism of shielding users from implementation details is not restricted to DFA. Learning algorithms for Mealy Machines will usually return MealyMachine<?, I, ?, O>, to abstract from the concrete choice of classes representing states and transitions. They can be dealt with in the same fashion.