Java泛型、接口和类继承
以抽象类为例:Java泛型、接口和类继承,java,generics,Java,Generics,以抽象类为例: public abstract class Animal { ...} 以及界面: public interface Canine<T extends Animal> {...} (注意:选项取自vavr库) 此存储库用于以下类别: public abstract AbstractFinderClass<T extends Animal & Canine<T>> { private Class<T> anima
public abstract class Animal { ...}
以及界面:
public interface Canine<T extends Animal> {...}
(注意:选项
取自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);
}
}
公共抽象AbstractFinderClass{
私有类动物型;
公共AbstractFinderClass(类animalType){
this.animalType=animalType;
}
公共选项findMyAnimal(字符串id){
返回repository.findById(id,this.animalType);
}
}
然后以具体形式实施,包括:
public class DogFinder extends AbstractFinderClass<Dog> {
public DogFinder() {
super(Dog.class);
}
}
公共类DogFinder扩展了AbstractFinderClass{
公共寻狗器(){
超级(狗类);
}
}
现在,行return repository.findById(id,this.animalType)
导致两个错误:
this.animalType
的类型为Class
,而预期的类型为Class
,并且这些类型显然不兼容李>
Option
,而我得到的是Option
Dog
和T
能够兼容。
您能帮我解决这个问题吗?第一个问题是您有一个不必要的类型参数用于
DogFinder
。它是一个dog finder,因此它所查找的内容的类型参数是多余的(非常规命名的类型参数dog
可能表明存在问题)。应该是:
class DogFinder extends AbstractFinderClass<Dog> {
public DogFinder() {
super(Dog.class);
}
}
第三,除非我们缺少上下文,否则我相信您的犬科类型不需要是泛型的(除非事情必须复杂):
如果您需要一个专门的犬类查找器,只需更改存储库类,如下所示:
abstract class CanineFinderClass<T extends Animal & Canine>
implements Repository<T> {...}
我想知道存储库类应该如何实现。findById
方法不应该具有相同类型的擦除吗?您可以不在repository类中重载相同的方法,而将其转换为单个泛型方法吗?基本上选项findById(字符串id,类类型)代码>。我认为您会遇到错误,因为T
可能是存储库中未定义的类型,因此您会尝试执行不存在的方法。如果DogFinder
应该是AbstractFinderClass
的具体实现,为什么它没有extends
子句?我们无法确定您的t
是否为Dog
。事实上,为什么它甚至有Dog
作为通用参数?这会造成与Dog
类的混淆。你的代码实际上不会编译。我建议一个。您需要的基本上是Bloch的“类型安全异构容器”实现——您应该查看详细描述此方法的有效Java。在这种特殊情况下,您可能会发现它很有用。类型参数应该从类存储库移到findById方法中,因为存储库可以处理所有动物类型。@AlexeiKaigorodov想法是给定的存储库可以处理任何动物类型,而不是所有动物类型。因此,在实例化时,type参数将定义哪种动物类型。因此,当重用repo时,您会得到相同的类型(否则,每次方法调用时都必须传入animalType
参数)。主题启动程序的思想是存储库可以处理所有类型,而AbstractFinderClass可以处理任何类型。否则,就不需要两个不同的类,每个类都处理一些具体的动物类型。@AlexeiKaigorodov这正是我旁注的重点(我怀疑我们说的是同一件事)。给定的类型可以与任何动物类型一起工作(因此类型本身是泛型的),但是当创建存储库的实例时,它会绑定到一个具体的动物类型(因此方法不是泛型的)。OP最大的问题是DogFinder
上的(可能是偶然的)类型参数在DogFinder
上的额外参数上有问题,抱歉:我错误地删除了一段代码:/参见更新的问题。
class DogFinder extends AbstractFinderClass<Dog> {
public DogFinder() {
super(Dog.class);
}
}
interface Repository<T extends Animal> {
Option<T> findById(String id, Class<T> type);
}
interface Canine {
}
abstract class CanineFinderClass<T extends Animal & Canine>
implements Repository<T> {...}
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);
}
}