I just re-read this last bit. What Tom are basically doing here is
Animal<?> animal;
Object o = animal.get();
if( o instanceof Cat ) {
Cat c = (Cat) o; // neighbor's cat
}
else {
Dog d = (Dog) o; // stray dog
}
which is VERY very messy indeed.
What? That bears no resemblance at all to the code i posted above! Indeed,
it's the exact opposite!
My *whole point* is that you might want to deal with Animals
polymorphically, ie not by instanceofing. But because Animal is a
parameterised type, you have to write it as such, even though the type
parameter carries no useful information in that situation.
If the interface of Animal looks like this:
public abstract class Animal<T extends Animal> {
public void processUnknownAnimal();
public float getMass();
public String getName();
}
That is, *with no use of the type parameter T*, then it seems weird to be
writing:
Animal<?> a;
Rather than:
Animal a;
Because the ? doesn't appear in the definitions of any of the methods you
might call!
Then the code above becomes:
Animal<?> animal;
Object o = animal.get();
if( o instanceof Animal ) {
Animal a = (Animal) o;
a.processUnkownAnimal();
}
Or better yet:
Animal<? extends Animal> animal;
Animal a = animal.get();
a.processUnkownAnimal();
I think i understand why we're going at cross purposes here: you're
thinking about Animals you might get from an initial Animal, out of that
parameterised list - i assume that's what get() is doing. So let's add
that, with a slightly more illuminating name, to the class:
public abstract class Animal<T extends Animal> {
private List<T> offspring;
public T getFirstOffspring() {
return offspring.get(0);
}
}
public class Cat extends Animal<Cat> {
}
public class Dog extends Animal<Dog> {
}
Now, T does appear in the methods. But it's still redundant, as i will
explain ...
First of all, note that the return type of getFirstOffspring is not
Object, but T, where T extends Animal, so your instanceof and cast are
unnecessary, you can just write:
Animal<?> animal;
Animal<?> a = animal.getFirstOffspring();
a.processUnknownAnimal();
Okay, now on to the redundancy. If you're dealing with Animals purely
polymorphically, then the binding of T will always be ? (or Animal<?> or
something, the two are much the same in this context). The only situation
where it might not be is if you were specifically dealing with one kind of
Animal. There, you could write:
Animal<Dog> myDog;
But there, we know from the definitions above that myDog isn't just an
Animal, it's a Dog. So we might as well just write:
Dog myDog;
And thus the type binding is once again unnecessary.
In java, though, there's no way to get away from it, because java doesn't
have a way of writing 'whatever the concrete class of this object is' is
type declarations. Not that i'm advocating one be added - the lack of it
is a minor annoyance, and i can't see a good way of doing it that doesn't
introduce other terrifying horrors.
tom