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

Eri*_*son 6 java generics

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

服务界面是这样的:

public interface Service {...}
Run Code Online (Sandbox Code Playgroud)

然后,添加对Service接口的通用引用的基类,其中T扩展了Service,但是整个基类也实现了接口.像这样的东西:

public class ServiceBase<T extends Service> implements Service {...}
Run Code Online (Sandbox Code Playgroud)

你为什么要这样做?我注意到在实践中,ServiceBase的扩展始终使用与正在声明的类相同的类名; 所以这里没有任何神奇的多态效益.像这样的东西:

public class MyService extends ServiceBase<MyService> {...}
Run Code Online (Sandbox Code Playgroud)

并且,MyService类永远不是泛型的容器(例如,我不相信这是发出某种自包含列表的信号,其中MyService可以包含MyServices列表).

关于为什么有人会这样做的任何想法/想法?

dav*_*xxx 4

你为什么要这样做?我注意到,在实践中,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();
    }

}
Run Code Online (Sandbox Code Playgroud)

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

例如,以下子类将编译,因为我们不必将返回类型更改createService()为当前声明的类型。

没有泛型的 MyService

public class MyService extends ServiceBase {

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

}
Run Code Online (Sandbox Code Playgroud)

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

具有泛型的 ServiceBase

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

    public abstract T createService();

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

}
Run Code Online (Sandbox Code Playgroud)

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

MyService 与泛型

public class MyService extends ServiceBase<MyService> {

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

}
Run Code Online (Sandbox Code Playgroud)