我在使用 instanceof
运算符时遇到问题。我试图避免它。基本上,我有以下结构:
class Shape {}
class Triangle extends Shape {}
class Rectangle extends Shape {}
ShapeParser s;
while (s.hasNext())
parseShape(s.next()); // returns a Shape object
void parseShape(Triangle t) { // do stuff } // KEY POINT HERE
void parseShape(Rectangle t) { // etc }
我的要点是:我想对函数进行参数重载,但它没有按我的预期工作(编译错误)。我试图避免:
void parseShape(Shape s)
{
if (s instanceof Triangle) ...
}
更新:似乎共识是创建一个基类方法:parseShape() 来做 起重。我想澄清一下我的问题:这个问题的动机是相对于观察者模式而言的。假设我有以下 Observer 对象有效负载方法:
public void update(Observable obj, Shape objectPayload){}
// note: the objectPayload is usually of type Object
而不是执行:
public void update(Observable obj, Shape objectPayload)
{
if (objectPayload instanceof Triangle)
// do stuff
else if (objectPayload instanceof Rectangle)
// etc
}
我想做的事:
public void update(Observable obj, Shape objectPayload)
{
parseShape(objectPayload);
}
void parseShape(Triangle t) { } // do stuff
void parseShape(Rectangle t) { }
最佳答案
您可以将 parseShape
移动到每个 Shape 类中。或者,您可以使用访问者模式。 this thread 的解决方案中显示了一个巧妙的反射技巧这避免了 Java 中完整访问者模式的复杂性。
更新:
这是访问者模式的秘诀:
声明一个接口(interface):
public interface ShapeVisitor { visit(Triangle); visit(Rectangle); // ... }
在
Shape
中,声明一个抽象方法acceptVisitor
:class Shape { public abstract void acceptVisitor(ShapeVisitor visitor); }
在每个具体类中,实现
acceptVisitor
:class Triangle extends Shape { public void acceptVisitor(ShapeVisitor visitor) { visitor.visit(this); } }
声明您的
ParseVisitor
类以实现ShapeVisitor
并实现所有必需的方法(只需将每个parseShape
方法重命名为访问
)。
这样做的好处是,首先,它将解析代码保留在 Shape 层次结构之外,并将其集中在一个单独的解析类中;其次,如果您稍后决定需要执行一些其他操作(比如渲染),您可以应用相同的模式,无需更改任何 Shape 类。这种方法的一大缺点是,如果您决定添加另一个 Shape
子类,则必须更改所有实现 ShapeVisitor
的类。
关于java - instanceof 与多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6119087/