5

我确信这之前一定有人问过,但我似乎找不到类似的例子。我很了解多态性和方法重载,但这是一个看似简单的场景,但有一个让我无法理解的解决方案:

假设我有一个带有几个派生类的基类。我将在这个例子中使用形状

base Shape
derived Circle extends Shape
derived LineSeg extends Shape

等等

现在,shape 有一个名为 intersect(other) 的方法,用于测试另一个 shape 以查看它们是否相交。借助多态性,很容易看出 Circle、LineSeg 等如何实现它们自己的“相交”方法,并且通过方法重载,我可以轻松实现所有需要的组合。例如,

Circle.intersect(LineSeg)
Circle.intersect(Circle)
LineSeg.intersect(Circle)

等等

到目前为止,一切都很好。

问题是,如果我保留一个中央形状列表,我想这样做:

for some shape s
Foreach shape in Shapes
  if (s.intersect(shape)) - do something

目前,我不确定这是怎么可能的,因为方法重载选择了“相交”方法来匹配基本类型 Shape,而不是适当的参数类型。如果没有 if-else 链检查类型和向下转换,我怎么能做到这一点?

顺便说一句,我正在使用 Java,但我不确定该语言是否完全相关,因为它似乎是一个基本的设计问题。看起来很简单,我错过了什么?

谢谢!


在下面解决(谢谢!),请参阅那里的详细信息。基本上,通过在派生类中有一个回调,然后调用适当的方法(访问者模式?),您可以使用“this”关键字来调用正确的 intersect 方法,因为它具有所需的正确类型。

4

3 回答 3

4

My first thought was the visitor pattern, pretty much give every Shape two methods, one I'll call intersect(Shape) and one doIntersect() method per Shape type.

It would look about like this:

interface Shape {
    public abstract Intersection intersect(Shape other);

    public abstract Intersection doIntersect(Circle circle);

    public abstract Intersection doIntersect(LineSeg line);
}
class LineSeg implements Shape {
    @Override
    public Intersection intersect(Shape other) {
        return other.doIntersect(this);
    }

    Intersection doIntersect(Circle circle) {
        // Code to intersect with Circle
    }

    Intersection doIntersect(LineSeg other) {
       // Code to intersect with another Lineseg
    }
}

class Circle implements Shape {
    @Override
    public Intersection intersect(Shape other) {
        return other.doIntersect(this);
    }

    public Intersection doIntersect(Circle other) {
        // Code to intersect with another Circle
    }

    public Intersection doIntersect(LineSeg segment) {
        // Code to intersect with LineSeg
    }
}

You might want the doIntersect methods to be package private or chose different names than these though.

于 2013-05-20T00:04:53.803 回答
0

请参阅泛型 Jdk5

对于 Shapes <> 中的每个形状

于 2013-05-20T00:16:00.623 回答
0

您的形状类必须是抽象类,这意味着它不会被实例化,只有派生类 circle 和lineseg 具有实例。intersect 方法在形状上应该是虚拟的,所以当你遍历所有形状时,每个形状的 intersect 方法都会被调用

public abstract class Shape {

    boolean intersect(Shape s);
}

public class Circle extends Shape {

    boolean intersect(Shape s) {
        ...
        if( s instanceOf Circle ) { 
           .... // Circle intersects cicrcle
        } else if( s instanceOf Lineseg ) {
           .... // Circle intersects Lneseg
        } else {
          throw RuntimeException("Unrecognized shape");
        }

    }

}

public class Lineseg extends Shape {

    boolean intersect(Shape s) {
        ...
        if( s instanceOf Circle ) { 
           .... // Lineseg intersects circle
        } else if( s instanceOf Lineseg ) {
           .... // Lineseg intersects lineseg
        } else {
          throw RuntimeException("Unrecognized shape");
        }
    }

}
于 2013-05-20T00:17:53.857 回答