在Java中捕获instanceof

Joh*_*dke 22 java enums instanceof

在我的应用程序中,我有一个2d实体数组来表示网格.网格中的每个位置都可以为空或由实体占用(在这种情况下,它只是一个人或墙).现在我instanceof用来检查一个实体是一个人还是一堵墙.

我正在考虑为每个实体提供一个方法,该方法返回一个enum说明其类型的方法,即墙实体将返回EntityType.WALL.我想知道这是否是最好的想法,删除使用instanceofinstanceof适合在这种情况下?

Rob*_*ert 42

使用Tell,Do not Ask:而不是询问对象是什么,然后对此作出反应,告诉对象该做什么,然后墙或人们确定他们如何做他们需要做的事情.

例如:

而不是像这样的东西:

public class Wall {
    // ...
}

public class Person {
    // ...
}

// later
public class moveTo(Position pos) {
    Object whatIsThere = pos.whatIsThere();
    if (whatIsThere instanceof Wall) {
         System.err.println("You cannot move into a wall");
    }
    else if (whatIsThere instanceof Person) {
         System.err.println("You bump into " + person.getName());
    }
    // many more else branches...
}
Run Code Online (Sandbox Code Playgroud)

做这样的事情:

public interface DungeonFeature {
    void moveInto();
}

public class Wall implements DungeonFeature {
    @Override
    public void moveInto() {
        System.err.println("You bump into a wall");
    }

   // ...
}

public class Person implements DungeonFeature {
    private String name;

    @Override
    public void moveInto() {
        System.err.println("You bump into " + name);
    }

    // ...
}

// and later
public void moveTo(Position pos) {
    DungeonFeature df = currentPosition();
    df.moveTo(pos);
}
Run Code Online (Sandbox Code Playgroud)

这有一些优点.

首先,每次添加新的地下城功能时,您都不需要调整巨型树.

其次,地牢特征中的代码是自包含的,逻辑全部在所述对象中.您可以轻松测试并移动它.


Epi*_*rce 8

理论解决方案去除instanceof一个精致的方式是的使用访问者模式.工作原理是需要知道另一个元素是墙或人的对象将自身作为参数调用该对象,并且该特定对象回调,从而提供有关其类型的信息.

例,

public class Person {
    void magic() {
        if(grid.getAdjacent() instanceof Person) {
            Person otherPerson = (Person)grid.getAdjacent();
            doSomethingWith(otherPerson);
        } else if(grid.getAdjacent() instanceof Wall) {
            Wall wall = (Wall)grid.getAdjacent();
            doOtherThingWith(wall);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

可以变成

public class Person extends Entity {
    void magic() {
        grid.getAdjacent().visit(this);
    }

    void onVisit(Wall wall) {
        doOtherThingWith(wall);
    }

    void onVisit(Person person) {
        doSomethingWith(person);
    }

    public void visit(Person person) {
        person.onVisit(this);
    }
}

public class Wall extends Entity { 
    public void visit(Person person) {
        person.onVisit(this);
    }
}
Run Code Online (Sandbox Code Playgroud)


lig*_*igi 1

我会让 person 和 wall 继承自抽象超类(例如 Tile ),该超类具有返回枚举或 int 的方法 getType() ,并在 Wall 和 Person 中实现此方法,返回适当的值