为泛型的实现的类提供变量的扩展功能,为子类提供

问题描述 投票:0回答:2

我是泛型新手,正在研究基本上超出我的知识范围的事物,因此请耐心等待。也许我要问的是愚蠢的,但是我似乎找不到关于我想做的事情是否可行的明确答案,也许是因为我不知道要寻找的正确术语。

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

存储库类:

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();
    }
}

当我希望扩展我的服务并允许人们使用存储库的子类时出现问题。尽管许多实体都是基本实体,并且功能由通用功能覆盖,但有时需要特殊情况才能对实体执行附加功能。在设置中,实现/扩展了存储库,然后将该扩展类传递给服务(由于它是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);
    }
}

这使我可以在服务上执行自定义功能,而且还可以利用通用服务上的所有基本功能,而无需复制代码。但是,由于将repo中的变量GenericService声明为类型GenericRepo<T>,因此,只有实际在类型GenericRepo<T>上的那些函数才可用于通用服务类和/或对其进行扩展的任何内容。因此,尽管我将ExtendedRepo传递给我的ExtendedService,其超类已通过GenericRepo的子类创建并提供了ExtendedRepo类的实例,但我无法在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);
    }
}

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

java generics subclass extends
2个回答
1
投票

您可以在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);
    }
}

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


0
投票

GenericService具有类型为repoGenericRepo。您在ExtendedService的构造函数中所做的操作仅在运行时可见,即repo实例的运行时类型将为ExtendedService类型(前提是它仅在ExtendedService对象中)。但是在编译时,repo的类型为GenericRepoGenericRepo没有方法findObjectByWeirdKeyOnEntity。因此,如果要在ExtendedService类中使用它,则必须将其显式区分为ExtendedService。因此只需执行以下操作:return(((ExtendedRepo)this.repo).findObjectByWeirdKeyOnEntity(weirdKey);

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

© www.soinside.com 2019 - 2024. All rights reserved.