I really love using initializers to make constructing and configuring classes more understandable. Basically I prefer this:
new ClassObj().StartingFrom(1).EndingAt(5).IncrementBy(1).Backwards();
Rather than this:
new ClassObj(1,5,1,false);
This is a bit of a pain in Java when mixed with inheritance, as returning types default to as generic as possible. I've found a workable solution using self-referential inheritance (Java: returning subclass in superclass method signature), but I'm having some problems with it.
My issue is that the Parent class implements Iterable, but the generic type parameter gets lost, so the for-each loop wants to return an Object instead of a File.
Here's an SSCCE showing the behavior:
public class SSCCE {
private static abstract class Sentence<T extends Sentence<T>> implements Iterable<String> {
protected LinkedList<String> Words = new LinkedList<>();
abstract T self();
public T Say(String word) {
Words.add(word);
return self();
}
@Override
public Iterator<String> iterator () {
return Words.iterator();
}
}
static class QuietSentence extends Sentence<QuietSentence> {
public QuietSentence Whisper(String word) {
Say(word.toLowerCase());
return this;
}
@Override
QuietSentence self() {
return this;
}
}
static class LoudSentence extends Sentence<LoudSentence> {
public LoudSentence Shout(String word) {
return Say(word.toUpperCase());
}
@Override
LoudSentence self() {
return this;
}
}
static void PrintWords(Sentence words) {
for(Object obj : words) {
// I'd really like to avoid this cast
String word = (String)obj;
System.out.println(new StringBuilder(word).append(": ").append(word.length())
.toString());
}
}
public static void main (String[] args) {
QuietSentence peaceful_words = new QuietSentence().Say("Hello").Whisper("World");
PrintWords(peaceful_words);
LoudSentence noisy_words = new LoudSentence().Say("Hello").Shout("World");
PrintWords(noisy_words);
}
}
What's going on, and how can I fix it?
So it turns out the problem was that I was not specifying the type correctly. A minimal fix in the
PrintWords
function solves the problem.