接受超类作为参数,但在方法中使用子类

时间:2019-02-08 21:08:39

标签: java class generics polymorphism

预先感谢您的回答。 我可能没有掌握正确形成问题所需的所有必要知识,但是到了这里: 我有一堆扩展Shape超级类的类(圆形,矩形,点)。 我有一个静态类Geometry,它具有一种检查不同形状(圆形,矩形,三角形)之间的交集的方法。 在“几何”静态类中,我实现了“相交”方法以接受形状的任意组合

  public static boolean intersects(Rectangle rect, Point point) {
    return rectIntersectsPoint(rect, point);
  }
  public static boolean intersects(Circle circle, Point point) {
    return circleIntersectsPoint(circle, point);
  }
  public static boolean intersects(Circle circle, Rectangle rect) {
    return circleIntersectsRect(circle, rect);
  }

每种情况下还有更多。 现在,在我的程序中,我有一个方法必须检查交集并必须接受Shape的任何子类:

  List<Point> query(Shape shape) {
    if (Geo.intersects(this.b, shape)) {
      return this.found;
    }
   ......
  }

我这样使用它:

Rectangle rect = new Rectangle(10, 10, 200, 300);
found = qt.query(rect );

但是我收到一条错误消息:“该函数与期望的参数相交(例如,矩形,圆)”。

因此,我将一个Rectangle对象传递给query()方法,并且进展顺利,因为我可以接受“ Shape”的任何子类。但是,当我在方法中使用它时,它并不能保持其“矩形”类型,而是成为“形状”对象。

我考虑过为每个子类都使用查询方法,但是那样一遍又一遍,我将拥有相同的代码。

2 个答案:

答案 0 :(得分:3)

多态允许您为对象的实际类型调用适当的方法,而不管引用的引用类型如何。

双重调度允许您为两种对象类型调用适当的方法。

这是草图(未经编译或测试):

public abstract class Shape {
    public abstract boolean intersects( Shape that );

    public abstract boolean intersects(Rectangle that);
    public abstract boolean intersects(Circle that);
}

public class Circle extends Shape {
    public boolean intersects( Shape that ) {
        return that.intersects( this );   // 'this' is of type Circle
    }

    public boolean intersects( Rectangle that ) { ... }
    public boolean intersects( Circle that ) { ... }
}

public class Rectangle extends Shape {
    public boolean intersects( Shape that ) {
        return that.intersects( this );   // 'this' is of type Rectangle
    }

    public boolean intersects( Rectangle that ) { ... }
    public boolean intersects( Circle that ) { ... }
}

您可以通过定义一对中的一个来调用另一个来避免冗余,或者让两个方法都调用一个公共实现。前者的一个示例是:

public class Rectangle {
    ...
    public boolean intersects( Circle that ) {
       return that.intersects( this ); 
    }

现在,假设您将“圆”和“矩形”传递给以下方法。

public boolean intersects( Shape shape1, Shape shape2 ) {
    return shape1.intersects( shape2 );
}

在编译时,编译器不知道将调用哪种方法。但是在运行时,将调用Circle.intersects(Shape)方法。它将调用Rectangle.intersects( Circle )

答案 1 :(得分:-1)

您可以对嵌套的访问者使用经过修改的visitor pattern。为了简洁起见,我将演示两种形状:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
        }
    }