【问题标题】:I don't want to use "instanceof" in java , what do I do?我不想在 java 中使用“instanceof”,我该怎么办?
【发布时间】:2011-12-10 14:23:52
【问题描述】:

我有两个抽象类,分别称为 RobotGeometricElement。 它们中的每一个都有子类。 我需要构建一个包含RobotGeometricElement 的NxM 矩阵,所以 我已经写了另一个类并称之为Item,然后是RobotGeometricElement 从那个类继承。

代码如下:

public class Item {
    private Dot currentLocation;
    private boolean taken;

    public Item(Dot location) {
        int x = location.getXcomponent();
        int y = location.getYcomponent();
        currentLocation = new Dot(x,y);
        taken = false;
    }

    // more code 
}

public abstract class GeometricElement extends Item {

    private float area; 

    public GeometricElement(Dot location) {
        super(location);
    }
}


public abstract class Robot extends Item { 
    private float basketArea;

    /*  Constructor */

    public Robot(Dot location, float basketNewArea) {
        super(location);
        basketArea = basketNewArea;
    }

    // some more code 
}

负责存储Items 的类称为 Ground :

public class Ground {

    private Item[][] board;
    private Queue elementQueue;

    /*  Constructor */

    public Ground(int row,int col) {
        board = new Item[row][col];
        this.elementQueue = new Queue();
    }

    // more code 

    public void addElementsToRobot() {
        while (this.elementQueue.doesQueueHasItems()) {
            GeometricElement element = elementQueue.popElementFromQuque();
            int x = element.getXlocation();
            int y = element.getYlocation();
            if (this.board[x][y].isTaken()) {
                if (board[x][y] instanceof Robot) {
                    // add geometric element to the basket
                }
            }
        }
    }
}

如上所述,我需要在板上存储RobotGeometricElement。当我尝试从矩阵(“地面”中的“板”矩阵)读取时,问题就开始了:我似乎无法找到一种方法来判断单元格中是否有机器人或几何元素,而不使用 @ 987654333@.

【问题讨论】:

  • 为什么您需要知道您拥有的是Robot 还是GeometricElement?扩展基类的全部意义在于避免显式检查。
  • 为什么不想使用instanceof?在你的情况下,这似乎是最合乎逻辑的。
  • 因为机器人能够将 GeometricElement 添加到篮子中(抱歉之前没有提及)。
  • @ron:如果您只想访问Robot 实例,您可能不应该维护一个通用Items 的容器。使用基类的全部意义在于您可以愉快地说“我不在乎”。
  • Oli,我这里别无选择。这是作业的规则:使用 NxM 矩阵,并将 Robot/GeometricElement 存储在其中。我认为您确实是对的,但我没有在这里选择。

标签: java inheritance abstract-class


【解决方案1】:

我当然不知道你的目标,但从我的头上:

我个人会使用 Composite 模式对其进行重构,以便您可以以统一的方式访问所有元素。至于没有实例的确定,您可以在您的 Item 类上有一个抽象方法来区分彼此。或者你可以让公共财产这样做。或者您可以提供更好的设计。

这实际上取决于您要达到的目标。 Instanceof 实际上可能是您问题的解决方案,但通常它指向更深层次的设计问题。

【讨论】:

    【解决方案2】:

    这里有一些替代方法,使用Object.getClass()返回的Class对象:

    • 使用Class.isAssignableFrom(Class) 来测试Class object 是否是(比如)Robot 的子类。

    • 将其与叶类的 Class 对象进行比较。

    • Class.getName()等返回的字符串做一些事情。

    或者您可以将抽象方法 boolean isARobot() 添加到 Item 类。

    或者您可以定义一个enum,其值表示Item 的直接子类。

    但是,这些都与instanceof 做几乎相同的事情......所以(IMO)你没有取得任何成就。当然,您还没有消除使用instanceof 的“代码味道”。

    【讨论】:

    • 是的,抽象方法和枚举可以说比instanceof更臭了。
    • @OliCharlesworth - 他们更臭,IMO。
    【解决方案3】:

    我喜欢使用复合设计模式的想法。非常优雅:)

    管理两个矩阵,一个用于机器人,一个用于几何对象。

    使用这些,您可以通过检查哪个矩阵占用了该字段来轻松确定给定坐标处的项目是一个还是另一个。

    不过,您必须小心避免在两个矩阵中的这些坐标上出现某些东西。

    正如我所说,不那么优雅,但仍然没有 instanceof :)

    【讨论】:

      【解决方案4】:

      鉴于这是家庭作业,“instanceof”是最简单的,因此可能是最好的方法,尽管它根本不是面向对象的,而且绝对是代码味道。

      一种更高级的方法是使用“双重调度”,也就是访客模式。 http://www.javaworld.com/javaworld/javatips/jw-javatip98.html有一个很好的解释

      【讨论】:

        【解决方案5】:

        毫无疑问,我的建议是您必须使用 instanceof。

        但另一种可能是:

         Object obj = ... //Robot or GeometricElement
         try {
             Robot robot =  (Robot) obj;
             // Do your logic for robot here
         } catch (ClassCastException ex){
             GeometricElement ge = (GeometricElement) obj;
             // Do your logic for geometric element here
         }
        

        【讨论】:

        • 嗯,我认为不应该以这种方式使用异常捕获。我的意思是,异常是不规则的事情,您不想发生但尝试解决。然而,在他的情况下,他知道会发生什么。我知道你可以做到这一点,但至少可以说我认为这是个坏习惯。顺便说一句,这是语义,性能方面,是一样的
        • @TomášPlešek 你是对的,这是因为我建议他必须使用 instanceof
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 1970-01-01
        • 2021-07-15
        • 2021-10-01
        • 2022-12-01
        • 2011-09-27
        相关资源
        最近更新 更多