我确信之前一定要问过,但我似乎无法找到类似的例子。我理解多态性和方法重载很好,但这是一个看似简单的场景,其解决方案让我无法理解:
假设我有一个带有几个派生类的基类。我会在这个例子中使用形状
base Shape
derived Circle extends Shape
derived LineSeg extends Shape
等
现在,shape有一个名为intersect(other)的方法,它测试另一个形状以查看它们是否相交。通过多态性,很容易看出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
目前,我不确定这是怎么可能的,因为方法重载选择“intersect”方法来匹配基类型Shape,而不是相应的参数类型。如何在没有if-else链检查类型和向下转换的情况下进行此操作?
顺便说一句,我使用的是Java,但我不确定该语言是否完全相关,因为它似乎是一个基本的设计问题。看起来很简单,我错过了什么?谢谢!
解决下面(谢谢!),请参阅那里的详细信息。基本上,通过在派生类中调用然后调用适当的方法(访问者模式?),您可以使用“this”关键字来调用正确的交叉方法,因为它具有所需的正确类型。
答案 0 :(得分:4)
我的第一个想法是访问者模式,几乎给每个Shape两个方法,每个Shape类型我会调用intersect(Shape)
和一个doIntersect()
方法。
看起来像这样:
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
}
}
您可能希望doIntersect方法是包私有的,或者选择不同于这些的名称。
答案 1 :(得分:0)
参见Generics Jdk5
对于Shapes<>
中的每个形状答案 2 :(得分:0)
你的shape类必须是一个抽象类,这意味着它不会被实例化,只有派生类circle和lineseg才有实例。相交方法应该是虚拟的形状,因此当您遍历所有形状时,每个形状的交叉方法称为
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");
}
}
}