使用正确的返回类型覆盖通用getter

时间:2015-09-03 19:45:08

标签: java generics inheritance

在尝试创建一个小型系统时,我遇到了Java泛型的问题。

public void bar(){
    final Shape shape = new Shape();
    final Painter<Shape> shapePainter = shape.getPainter();

    final Circle circle = new Circle();
    final Painter<Circle> circlePainter = circle.getPainter();
}

class Shape {

    public Painter<? extends Shape> getPainter(){
        return new Painter<>(this);
    }

}

class Circle extends Shape {

    @Override
    public Painter<Circle> getPainter(){
        return new CirclePainter(this);
    }

}

class Painter<E extends Shape> {

    public Painter(final E element){
        // ...
    }

    public void paint(final E shape){
        // ...
    }

}

class CirclePainter extends Painter<Circle> {

    public CirclePainter(final Circle element){
        super(element);
    }

    @Override
    public void paint(final Circle shape){
        // ...
    }
}

编译时失败,第3行(final Painter<Shape> shapePainter = shape.getPainter();)上的错误表示:

  

不兼容的类型:

     

必需:Bar.Painter&lt; org.example.Bar.Shape&GT;

     

发现:Bar.Painter&lt;捕获&LT; ?扩展org.example.Bar.Shape&gt;&gt;

然后可以通过将故障线路更改为:

来解决此问题
final Painter<?> shapePainter = shape.getPainter();

然而,后来的电话如下:

shapePainter.paint(shape);

将抛出另一个例外:

  

无法应用Painter中的paint(capture&lt;?extends org.example.Bar.Shape&gt;)

     

to(org.example.Bar.Shape)

我觉得我错过了一些简单的Java泛型,可以帮助解决这个问题。我试图摆弄Shape#getPainter的返回类型,但这通常会导致Circle#getPainterbar中的编译器错误似乎没有任何可能的解决方案。

如果泛型无法做到这一点,还有哪些其他解决方案可用?

1 个答案:

答案 0 :(得分:0)

您需要使用CRTP:

使整个类具有通用性
class Shape<T extends Shape<T> {

    public Painter<T> getPainter(){
        return new Painter<>(this);
    }

}
class Painter<E extends Shape<E>> { ... }