当前位置: 首页 > 知识库问答 >
问题:

在同时实现同一类的基类中使用泛型的好处

慎风畔
2023-03-14

我最近在我没有编写的代码中遇到了这个场景,虽然这种方法可能有一些设计上的好处,但我似乎无法从我自己的大脑中挤出这个原理。所以在我看起来很傻之前,我希望这里有一些反馈。

服务接口如下所示:

public interface Service {...}

然后是一个向服务接口添加泛型引用的基类,其中T扩展了服务,但随后整个基类也实现了该接口。类似这样的事情:

public class ServiceBase<T extends Service> implements Service {...}

你为什么要这么做?我注意到,在实践中,ServiceBase的扩展总是使用与正在声明的类名相同的类名T;所以这里并没有什么神奇的多态好处。类似这样的事情:

public class MyService extends ServiceBase<MyService> {...}

而且,MyService类从来不是泛型的容器(例如,我不认为这是在发出某种自包含列表的信号,MyService可以包含MyServices的列表)。

对为什么有人会这么做有什么想法吗?

共有1个答案

胡越
2023-03-14

你为什么要这么做?我注意到,在实践中,ServiceBase的扩展总是使用与正在声明的类名相同的类名T;所以这里并没有什么神奇的多态好处。

泛型并不是用来创造魔法多形体的。它主要是一种在编译时为类型添加约束的方法,以便在运行时减少笨拙的强制转换和错误类型。

在您的示例中,假设ServiceBase类是抽象的,并且具有一个process()方法,该方法需要在每次调用时创建一个我们以参数化类型声明的具体类的新实例。
我们将此抽象方法称为createService()

不使用泛型,我们可以像public abstract ServiceBase createService()那样声明方法

没有泛型的ServiceBase

public abstract class ServiceBase implements Service {

    public abstract ServiceBase createService();

    @Override
    public void process() {
         createService().process();
    }

}

通过此声明,concrete类可以返回ServiceBase的任何实例。

例如,下面的子类将进行编译,因为我们没有被迫将createService()的返回类型更改为当前声明的类型。

没有泛型的MyService

public class MyService extends ServiceBase {

    @Override
    public ServiceBase createService() {    
        return new AnotherService();
    }

}

但如果我在基类中使用泛型:

带有泛型的ServiceBase

public abstract class ServiceBase<T extends Service> implements Service {

    public abstract T createService();

    @Override
    public void process() {
         createService().process();
    }

}

具体类别无选择,它被迫用声明的参数化类型更改createService()的返回类型。

带泛型的MyService

public class MyService extends ServiceBase<MyService> {

    @Override
    public MyService createService() {  
        return new MyService();
    }

}
 类似资料:
  • 我被分配了一个问题:编写一个通用的加权元素 到目前为止,我已经创建了类并实现了Compariable,但在为W创建compareTo()方法时遇到了问题。我有: 我遇到的问题是,当我比较权重时,没有找到数据的权重。还有没有其他我必须创建的方法来正确地拥有一个在其中一个变量上实现可比较的类?谢谢你的帮助

  • 考虑一个具有的API,如下所示: 很简单,只有页面大小和跳过计数属性。 此外,现在我还有一些类,它们也包含但未分页。 在我的测试中,我希望他们都能实现一个接口,这样我就可以用一些更基本的测试来生成一个通用的基本测试类。为此,我添加了我认为会起作用的内容: 我将PagedResults更改为: 错误 但现在编译器抱怨PagedResultBase继承的所有地方的使用情况(?)从。 但是,如果我将接口

  • 问题内容: 我对此进行了扩展,应该可以帮助我在上下文之间传输对象: 现在它返回的对象,我应该将其强制转换为我想要的类,如下所示: 有没有办法避免这种无用的转换,如果我从类的对象调用使其返回类型? 问题答案: 更新: 有关更好的解决方案 与如何在NSManagedObjectSwift扩展中如何创建托管对象子类的实例中类似,这可以使用通用的辅助方法来完成: 请注意,我已将返回类型更改为。 并 没有

  • 我在覆盖接口中声明的方法时遇到了一些问题,该方法使用泛型参数作为其异常,并使用泛型作为其参数之一。为了说明,我编写了以下代码接口 通过javac运行,我得到 请注意,在接口中,metodoA和metodoB之间的唯一区别在于它们的参数。 为什么Implementadora(Implementadora)的metodoB(metodoB)(代码)不重写Interfaz(代码),但重写metodoB(

  • 这是我的场景,我有三节课。 这里translate方法返回动物对象,但我需要使用相同的方法返回狗和猫类型,而不需要进行类型转换。我知道我必须在这里使用泛型,但是我如何编辑translate方法来支持泛型,这样我就可以将类类型传递给它的参数,如果使用Cat参数调用它就返回Cat对象,如果使用动物参数调用它就返回动物对象,如果使用Dog参数调用它就返回Dog对象。 例如:-而不是 Cat newCat