在Java中捕获instanceof

时间:2015-11-22 23:02:44

标签: java enums instanceof

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

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

6 个答案:

答案 0 :(得分:41)

使用Tell, Don't 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...
}

做这样的事情:

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);
}

这有一些优点。

首先,每次添加新的地下城功能时,您都不需要调整巨树(如果是其他树)。

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

答案 1 :(得分:8)

删除a refined wayinstanceof的理论解决方案是使用Visitor Pattern。它的工作原理是,需要知道另一个元素是一个墙或人的对象是否以自身为参数调用该对象,并且该特定对象回调,从而提供有关其类型的信息。

实施例,

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);
        }
    }
}

可以成为

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);
    }
}

答案 2 :(得分:0)

我会让person和wall继承自一个抽象的超类(例如Tile),它有一个方法getType()返回一个enum或int,并在Wall和Person中实现这个方法,返回相应的

答案 3 :(得分:0)

答案非常好,这里没什么可说的,但是如果我在这种情况下,并且如果它被允许,那么我将去掉一个可能值为0的2d int数组(默认分配为空)和1,2为人或墙。

答案 4 :(得分:-1)

this other question所述,现代Java编译器在 instanceof 等操作中非常高效。你可以使用它。

事实上,其中一个提供了测试 instanceOf 和字符串比较的答案, instanceOf 明显更快。我建议你坚持使用它。

答案 5 :(得分:-1)

利普的回答是正确的。 (无论是谁投票,我都不知道他们在想什么。)作为替代方案,请考虑一下:

abstract class Tile
{
    public final EntityType type;

    protected Tile( EntityType type )
    {
        this.type = type;
    }
}

abstract class Pedestrian extends Tile
{
    public Pedestrian()
    {
        super( EntityType.PEDESTRIAN );
    }
}

abstract class Wall extends Tile
{
    public Wall()
    {
        super( EntityType.WALL );
    }
}

这背后的基本原理是实体的“类型”是实体的永久特征,因此它适合在构造函数中指定并在final成员字段中实现。如果它是由虚方法返回的(java用语中的非最终方法),那么后代可以在一个时间点自由返回一个值,在另一个时间点返回另一个值,这会造成严重破坏。

哦,如果你真的无法忍受公众最后的成员,请继续为它添加一个吸气剂,但我的建议是,没关系纯粹主义者,没有吸气剂的公共最终成员完全没问题。

相关问题