有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为泛型的已实现类的变量提供了扩展功能

我不熟悉泛型,并且深入研究了一些基本上超出我知识范围的东西,所以请耐心听我说。也许我所问的很愚蠢,但我似乎无法找到一个明确的答案来说明我想做的事情是否可行,也许是因为我不知道要寻找的正确术语

我有两个Java类,它们由一个T类型的实体参数化——一个存储库和一个服务。由于我的所有存储库和所有服务都将执行一些相同的基本任务,因此我的通用repo和服务已经实现了上述任务,并通过受保护的函数将它们提供给任何扩展它们的对象。到目前为止,一切都很顺利。目前它们看起来像这样:

存储库类:

public interface GenericRepo<T> {
    protected T findObject();
}

服务类别:

public class GenericService<T> {
    private GenericRepo<T> repo;

    public GenericService(GenericRepo<T> repo) {
        this.repo = repo;
    }

    protected T findObject() {
        return this.repo.findObject();
    }
}

当我希望扩展我的服务并允许人们使用存储库的子类时,问题就出现了。虽然许多实体是基本的,并且功能包含在通用功能中,但有时需要特殊情况来对实体执行附加功能。在设置中,实现/扩展repo,然后将扩展类传递给服务(服务接受它,因为它是GenericRepo<T>类型)。具体的回购协议如下所示:

public class ExtendedRepo implements GenericRepo<Entity> {
   protected Entity findObjectByWeirdKeyOnEntity(String weirdKey) {
       //awesome code that does stuff here
   }
}

我还将该服务声明为通用服务,因为该服务上也有许多自定义功能的可能性。因此GenericService也扩展如下:

public class ExtendedService extends GenericService<Entity> {
    public ExtendedService(ExtendedRepo repo) {
        super(repo);
    }

    public Entity findObjectByWeirdKeyOnEntity() {
        // Do stuff to generate weird key to search by
        return this.repo.findObjectByWeirdKeyOnEntity(weirdKey);
    }
}

这允许我在服务上执行自定义函数,但也可以利用通用服务上的所有基本函数,而无需复制代码。但是,由于GenericService中的变量repo被声明为类型GenericRepo<T>,因此只有类型GenericRepo<T>上的那些函数才可用于泛型服务类和/或扩展它的任何对象。因此,尽管我正在将ExtendedRepo传递给我的ExtendedService,它的超类通过ExtendedRepo的子类创建并提供了GenericRepo类的实例,但我不能使用GenericService上声明的变量调用ExtendedRepo上的任何函数上面代码块中的代码失败-this.repo不知道函数findObjectByWeirdKeyOnEntity,因为它是GenericRepo<T>类型的变量。目前,要在扩展存储库上使用任何自定义函数,我已完成以下操作:

public class ExtendedService extends GenericService<Entity> {
    private ExtendedRepo extendedRepo;

    public ExtendedService(ExtendedRepo repo) {
        super(repo);
        this.extendedRepo = repo;
    }

    public Entity findObjectByWeirdKey() {
        return this.extendedRepo.findObjectByWeirdKeyOnEntity(weirdKey);
    }
}

在扩展服务中为存储库重新声明和保留一个单独的变量似乎是错误的,因为我基本上保留了同一类的两个实例,这样我就可以在扩展类中使用一个自定义函数,同时还可以使用超类的所有公共功能。是否有任何方法可以将GenericService上的变量GenericRepo创建为任何类型,该类型扩展了GenericRepo,从而允许扩展GenericService的类在GenericRepo类的扩展版本上使用自定义方法


共 (2) 个答案

  1. # 1 楼答案

    GenericServicerepo类型的GenericRepo。在ExtendedService的构造函数中所做的事情只在运行时可见,即repo实例的运行时类型将是ExtendedService类型(前提是它仅在ExtendedService对象中)
    但是在编译时,repoGenericRepo类型,GenericRepo没有findObjectByWeirdKeyOnEntity方法
    因此,如果你想在ExtendedService类中使用它,你必须显式地将其大小写为ExtendedService。所以只需这样做:返回((ExtendedRepo)这个。回购协议)。FindObjectByWeirdKeyOnenity(古怪钥匙)

    或者

    使用@Banannon's solution。这也是一个很好的例子

  2. # 2 楼答案

    您可以向GenericService添加一个类型参数,该参数将表示GenericRepo的类型:

    public class GenericService<R extends GenericRepo<T>, T> {
        protected R repo;
    
        public GenericService(R repo) {
            this.repo = repo;
        }
    
        protected T findObject() {
            return this.repo.findObject();
        }
    }
    
    public class ExtendedService extends GenericService<ExtendedRepo, Entity> {
        public ExtendedService(ExtendedRepo repo) {
            super(repo);
        }
    
        public Entity findObjectByWeirdKeyOnEntity(String weirdKey) {
            return this.repo.findObjectByWeirdKeyOnEntity(weirdKey);
        }
    }
    

    注意:在上一个示例中,您保留了对同一实例的两个引用,但不是同一类的两个实例