使用Java中的泛型保证协变返回类型 [英] Guarantee covariant return type with generics in Java

查看:104
本文介绍了使用Java中的泛型保证协变返回类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我有一个名为 Point 的类,其方法是 neighbors(),它返回一个数组of Point s:

I have a class called Point, with a method neighbors() that returns an array of Points:

public class Point {
    public Point[] neighbors() { /* implementation not shown */ }
}

我有一个 Point 的子类,名为 SpecialPoint ,它会覆盖邻居()返回 SpecialPoint 的数组,而不是 Point s。我认为这称为协变返回类型。

I have a subclass of Point, called SpecialPoint that overrides neighbors() to return an array of SpecialPoints instead of Points. I think this is called covariant return types.

public class SpecialPoint extends Point {
    public SpecialPoint[] neighbors() { /* implementation not shown */ }
}

在另一个类中,我想使用泛型

In a separate class, I want to make use of Point and SpecialPoint with generics

public <P extends Point> P doStuff(P point) {
    P[] neighbors = point.neighbors();
    // more stuff here including return
}

这将无法编译,因为编译器只能保证 P Point 的某个子类,但不能保证<的每个子类 Point 将覆盖 neighbors()返回一个自己的数组,因为我碰巧用 SpecialPoint ,因此Java只知道 P#neighbors()返回 Point [] ,不是 P []

This will not compile, because the compiler can only guarantee that P is some subclass of Point, but there is no guarantee that every subclass of Point will override neighbors() to return an array of itself as I happen to have done with SpecialPoint, so Java only knows that P#neighbors() returns Point[], not P[].

我如何保证每个子类重写 neighbors() 有一个协变返回类型,所以我可以用泛型?

How do I guarantee that each subclass overrides neighbors() with a covariant return type so I can use it with generics?

推荐答案

您可以使用界面:

public interface Point<P extends Point<P>> {
    P[] neighbors();
}

public class SimplePoint implements Point<SimplePoint> {
    @Override
    public SimplePoint[] neighbors() { /* ... */ }
}

public class SpecialPoint implements Point<SpecialPoint> {
    @Override
    public SpecialPoint[] neighbors() { /* ... */ }
}

然后:

public <P extends Point<P>> P doStuff(P point) {
    P[] neighbors = point.neighbors();
    /* ... */
}






如果你仍然需要在实现之间分解代码,那么最好使用抽象类:


If you still need to factorize code between the implementations, then better use an abstract class:

public abstract class Point<P extends Point<P>> {
    public abstract P[] neighbors();
    public void commonMethod() { /* ... */ }
}

public class SimplePoint extends Point<SimplePoint> { /* ... */ }

public class SpecialPoint extends Point<SpecialPoint> { /* ... */ }

这篇关于使用Java中的泛型保证协变返回类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆