Java泛型,接口和类继承

时间:2019-01-02 14:34:52

标签: java generics

考虑抽象类:

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)导致两个错误:

  1. 在第二个参数上,this.animalType的类型为Class<T>,而期望的类型为Class<Dog>,这些显然不兼容;
  2. 返回类型应该为Option<T>,而我得到的是Option<Dog>

恐怕我缺少一些“小”细节,因为我希望DogT是兼容的。 您能帮我解决问题吗?

1 个答案:

答案 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);
    }
}
相关问题