【发布时间】:2019-01-02 23:14:25
【问题描述】:
考虑抽象类:
public abstract class Animal { ...}
和界面:
public interface Canine<T extends Animal> {...}
我已经定义了具体的类:
public class Dog extends Animal implements Canine<Dog> {...}
public class Wolf extends Animal implements Canine<Wolf> {...}
我想构建一个repository 类来访问动物数据库并返回它们。我是这样定义的:
public interface Repository {
Option<Dog> findById(String id, Class<Dog> type);
Option<Wolf> findById(String id, Class<Wolf> type);
(注意:Option 取自 vavr 库)
此存储库用于以下类:
public abstract AbstractFinderClass<T extends Animal & Canine<T>> {
private Class<T> animalType;
public AbstractFinderClass(Class<T> animalType) {
this.animalType = animalType;
}
public Option<T> findMyAnimal(String id) {
return repository.findById(id, this.animalType);
}
}
这又以具体形式实现:
public class DogFinder extends AbstractFinderClass<Dog> {
public DogFinder() {
super(Dog.class);
}
}
现在,return repository.findById(id, this.animalType) 行导致两个错误:
- 在第二个参数上,
this.animalType是Class<T>类型,而预期类型是Class<Dog>,这些显然是不兼容的; - 返回类型应为
Option<T>,而我得到Option<Dog>
恐怕我遗漏了一些“小”细节,因为我希望 Dog 和 T 兼容。
你能帮我解决这个问题吗?
【问题讨论】:
-
我想知道
Repository类应该如何实现。findById方法不应该具有相同的擦除类型吗? -
不是在存储库类中重载相同的方法,你能把它变成一个单一的泛型方法吗?基本上是
Option<A> findById<A>(String id, Class<A> type);. -
我认为您遇到了错误,因为
T可能是您的Repository中未定义的类型,因此您将尝试执行不存在的方法。跨度> -
如果
DogFinder应该是AbstractFinderClass的具体实现,为什么它没有extends子句?我们不能确定您的T是Dog。事实上,为什么它甚至有Dog作为泛型参数?这会造成与Dog类的混淆。您的代码实际上不会编译。我建议minimal reproducible example。 -
您所要求的基本上是 Bloch 的“Typesafe Heterogenous Container”实现——您应该查看详细描述此方法的 Effective Java。在这种特殊情况下,您可能会发现 this answer to a related question 很有用。