考虑抽象类:
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
是兼容的。
您能帮我解决问题吗?
答案 0 :(得分:2)
第一个问题是DogFinder
的类型参数不必要。这是一个寻狗器,因此它所发现的类型参数是多余的(非常规命名的类型参数Dog
可能表明存在问题)。应该是:
class DogFinder extends AbstractFinderClass<Dog> {
public DogFinder() {
super(Dog.class);
}
}
第二,您的Repository
类型具有绑定到特定类型的方法。这没有什么意义,因为您希望它是通用的。因此,您可以仅使用一种方法,(可选)使存储库本身具有通用性(在解决签名冲突问题的过程中):
interface Repository<T extends Animal> {
Option<T> findById(String id, Class<T> type);
}
第三,除非我们缺少上下文,否则我相信您的Canine
类型不需要是通用的(除非必须进行复杂的处理):
interface Canine {
}
如果您需要专用的寻犬器,只需更改存储库类,就像这样:
abstract class CanineFinderClass<T extends Animal & Canine>
implements Repository<T> {...}
请注意,DogFinder
存储库是多余的,除非它提供特殊的狗方法,例如findAllPuppies()
。否则,将AbstractFinderClass
具体化就足够了,因为类型是通用的(仅作为示例):
class AnimalFinderClass<T extends Animal> implements Repository<T> {
Repository<T> repository;
private Class<T> animalType;
public AbstractFinderClass(Class<T> animalType) {
this.animalType = animalType;
}
public Option<T> findMyAnimal(String id) {
return repository.findById(id, this.animalType);
}
}