abstract class AnimalSerializer<E extends Animal> {
/**
* The type E (which extends Animal) is important here.
* I want to be able to write data that is specific to a subclass of an animal.
*/
abstract void writeAnimal(E animal);
abstract Animal readAnimal();
}
abstract class Animal {
AnimalSerializer<? extends Animal> serializer;
Animal(AnimalSerializer<? extends Animal> speciesSerializer) {
serializer = speciesSerializer;
}
void writeAnimalToFile() {
// This line fails to compile
serializer.writeAnimal(this);
}
}
class DogSerializer extends AnimalSerializer<Dog> {
@Override
void writeAnimal(Dog animal) {
// Write the stuff that is specific to the dog
// ...
}
@Override
Animal readAnimal() {
// Read the stuff specific to the dog, instantiate it, and cast it as an animal.
// ...
return null;
}
}
class Dog extends Animal {
String dogTag = "Data specific to dog.";
Dog() {
super(new DogSerializer());
}
}
我的问题与编译失败的行(serializer.writeAnimal(this)
)有关。我不得不第一次提高语言规范以了解关于this
关键字的更多信息,但是我认为问题在于“ this”关键字的类型为Animal
,并且有界通配符泛型<? extends Animal>
仅支持类型为Animal的子类,而不支持Animal
类型本身。
我认为编译器应该知道,this
关键字的类型必须是扩展Animal的对象(假设无法实例化Animal),而{{1} }关键字仅适用于已存在的对象。
编译器为什么不知道这一点?我的猜测是,有一种情况可以解释为什么不能保证this
关键字是Animal的子类。
此外,这种模式是否从根本上存在缺陷?
答案 0 :(得分:2)
您的serializer
通用类型是? extends Animal
。您的this
类型为Animal
,也可以视为? extends Animal
。但是,这两个?
是不同的类型。没有限制让编译器知道它们是同一类型。
例如,我写了一个Cat
类
class Cat extends Animal {
Cat(){
super(new DogSerializer()); // this is ok for your generic
}
}
这就是为什么编译器会给您一个错误。
答案 1 :(得分:0)
除了Dean所说的:
您可以将Animal
设为通用:Animal<S extends Animal>
然后,序列化器变为AnimalSerializer<S> serializer
。现在,它引用了Animal的“已知”子类。
并且扩展名变成Dog extends Animal<Dog>
。不幸的是,无法阻止Cat extends Animal<Dog>
。
您仍然必须强制执行以下行:serializer.writeAnimal((S)this);
但是现在可以这样做,因为您知道要强制转换为哪个类。
这是泛型?
的缺点。