如何解决 Java 泛型通配符/抽象歧义问题?
下面的代码是我的项目正在使用的模式的简化版本。我们使用的标准模式是为每个对象类型都有一个 Writer。对于一种抽象类型的子类型(在本例中为 Animal),我希望使用枚举来查找正确的作者。
abstract class Writer<T> {
abstract void write(T value);
}
abstract class Animal {
abstract AnimalType getType();
}
class Cat extends Animal {
AnimalType getType() { return AnimalType.CAT; }
}
class CatWriter extends Writer<Cat> {
void write(Cat value) { }
}
// The AnimalType stores a reference to the correct writer for the Animal subclass
enum AnimalType {
CAT(new CatWriter());
Writer<? extends Animal> writer;
Writer writerThatWorksWithWarning;
Writer<Animal> writerThatWorksButCantBeAssigned;
AnimalType(Writer<? extends Animal> writer) {
this.writerThatWorksWithWarning = writer;
this.writer = writer;
// ERROR: Incompatible Types
this.writerThatWorksButCantBeAssigned = writer;
}
}
示例用例:
class Test {
public static void main(String... args) {
Animal value = new Cat();
// ERROR: write (capture<? extends Animal) in Writer cannot be applied to (Animal)
value.getType().writer.write(value);
// WARNING: Unchecked call
value.getType().writerThatWorksWithWarning.write(value);
// This line works fine here - but can't be assigned above
value.getType().writerThatWorksButCantBeAssigned.write(value);
}
}
我认为我的问题与此问题中的问题类似: 带有通配符的 Java 泛型,但是我不知道如何解决它。
我已将收到的内联错误和警告放在评论中。
有什么想法吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为这里的问题是你不能用枚举来表示类型层次结构,因此无法告诉类型系统 for
enum { CAT, DOG; }
CAT
的类型应为CAT extends Animal
,而DOG
的类型应为DOG extends Animal
。那么既然你已经有了一个类层次结构,为什么不使用它呢?即:在我看来,您真正使用枚举的目的更像是
>
的哈希图,有点像内置的单例。您可以做到这一点,但只能通过隐藏类型来实现。I think the issue here is that you can't represent a type hierarchy with an enum, so there's no way to tell the type system that for
enum { CAT, DOG; }
theCAT
should type toCAT extends Animal
and theDOG
types toDOG extends Animal
. So But since you have a class hierarchy already, why not use that? i.e. something like :It seems to me that what you're really using the enum for is something more like a hashmap of
<Class, Writer<Class>>
, sort of a built in singleton. You can do this, but only by hiding the types.我希望动物不知道作家。他们毕竟是动物。
您可以拥有一个
Map
,并且对于其中的每个条目,您可以维护键Class
和值Writer 。
与X
类型大致相同。我们无法用类型来表达这种关系,因此必须在某些地方进行强制转换。如果查找某个类型失败(例如 Cat),请尝试再次查找其超类型(动物)类型安全的公共 API 可以设计为假设
我们没有直接映射到 Cat 的 Writer,但我们确实有一个
Writer
对于 Animal,那么将为 Cat.class 返回该 writer。没关系,因为那位作家确实接受所有动物。可以提供这种方便的方法:
从对象的类型中,可以找到合适的写入者,并且写入者将接受该对象。
I would have animals unaware of writers. they are animals after all.
You can have a
Map<Class,Writer>
, and for each entry in it, you maintain that the keyClass<X>
and valueWriter<X>
are about the same typeX
. We can't express that relation in types, so casts must be done at some places. If looking up fails for a type (say Cat), try looking up again with its super types (Animal)A type safe public API can be designed like
Suppose we don't have a Writer directly mapped to Cat, but we do have a
Writer<Animal>
for Animal, then that writer will be returned for Cat.class. That is ok, because that writer does accept all animals.This convenient method can be provided:
from the type of the object, a suitable writer can be found, and the writer will accept the object.
试试这个,
此外,我不确定你在做什么。但我相信 访问者模式 在这种情况下会派上用场。
上述解决方案有问题,下面的代码会破坏这个问题。
Try this instead,
Moreover, I am not sure what are you up to. But I believe that Visitor pattern will come handy in this case.
Problem with the above solution, the code below will break the thing.