【问题标题】:Why is "instanceof" not working?为什么“instanceof”不起作用?
【发布时间】:2016-10-10 20:51:10
【问题描述】:

我正在使用 Java instanceof,但它似乎不起作用。

我有 三个 扩展 Hero 类的 java 类。
Hero.java 类:

public abstract class Hero {

    protected int health;

    public Hero() { 
    }
}

其他三个类:

public class Archer extends Hero {
    public Archer() {
    }
}

public class Mage extends Hero {
    public Mage() {
    }
}

public class Warrior extends Hero {
    public Warrior() {
    }
}

我有这个主类WelcomeScreen.java

public class WelcomeScreen {

    private Archer archer;
    private Mage mage;
    private Warrior warrior;
    private Hero hero;

public WelcomeScreen() {

        // choose a hero (archer/mage/warrior)
        hero = archer;
        new Game(hero);
    }

    public static void main(String args[]) {
        new WelcomeScreen();
    }

}

实例化 Game.java

public class Game {

    public Game(Hero chosenHero) {

        if (chosenHero instanceof Mage) {
            System.out.println("you selected mage");
        } else if (chosenHero instanceof Archer) {
            System.out.println("you selected archer");
        } else if (chosenHero instanceof Warrior) {
            System.out.println("you selected warrior");
        } else {
            System.out.println("you selected NOTHING");
        }
    }

}

Game.java 中,代码用于检查 selectedHero 是否是 Archer.javaWarrior.javaMage.java,但我的结果是 “你没有选择任何东西”。为什么 instanceof 无法检查我是否已在 WelcomeScreen 中将其分配给 Archer.java

【问题讨论】:

  • archer 变量为空。 -- 你在哪里打电话给new Archer()
  • 你会想要学习使用调试器,然后练习使用它。同样大量使用instanceof 的结构会散发出代码气味,应该避免。
  • @HovercraftFullOfEels 嗯...好吧...闻起来是什么味道?
  • @RobotKarel314:我不知道,因为我从来没有近距离闻过它,但我知道它是not a good smell

标签: java oop polymorphism aggregation instanceof


【解决方案1】:

因为你的常量是null。当你说,

private Archer archer;

相当于

private Archer archer = null;

此外,您为每个实例创建了三个字段。我想你想做类似的事情

private static final Hero archer = new Archer();
private static final Hero mage = new Mage();
private static final Hero warrior = new Warrior();

另见What does it mean to “program to an interface”?

【讨论】:

  • 为什么你认为它们应该是静态的?
  • @shmosel 因为它们似乎是某种 RPG 的全局角色类型(单个玩家有四个 Hero 字段似乎有点奇怪)。或者,应该完全消除它们,并且操作可能只有一个实例 Hero hero 字段 (Hero hero = new Archer();)
  • 我怀疑hero 应该是WelcomeScreen 的实例变量,而之前的类型是因为OP 不知道如何分配新实例。
  • 我明白了。我实际上认为有一种方法可以只实例化用户选择的类。我从不想创建所有这些(并使用内存)。
  • @LawrenceLelo 当然可以,但用户必须指定它们(您已将其硬编码为“archer”)。
【解决方案2】:

替代解决方案:去掉 instanceof,因为它暗示了一种脆弱的刚性设计,很容易损坏。而是尝试使用其他更符合 OOP 的解决方案,例如继承,或者如果很复杂,还可以使用访问者设计模式。

例如,一个简单的继承结构可能看起来像:

public class WelcomeScreen {
    public WelcomeScreen() {

        // choose a hero (archer/mage/warrior)
        Hero hero = new Archer();
        new Game(hero);
    }

    public static void main(String args[]) {
        new WelcomeScreen();
    }
}

abstract class Hero {
    protected int health;
    // other shared fields such as String name,...

    public Hero() {
    }

    public abstract String getType();

    public int getHealth() {
        return health;
    }

}

class Archer extends Hero {
    public static final String TYPE = "Archer";

    public Archer() {
    }

    @Override
    public String getType() {
        return TYPE;
    }
}

class Mage extends Hero {
    public static final String TYPE = "Mage";

    public Mage() {
    }

    @Override
    public String getType() {
        return TYPE;
    }

}

class Warrior extends Hero {
    public static final String TYPE = "Warrier";

    public Warrior() {
    }

    @Override
    public String getType() {
        return TYPE;
    }

}

class Game {

    private Hero hero;

    public Game(Hero chosenHero) {
        this.hero = chosenHero;
        System.out.println("You selected a hero of type " + hero.getType());
    }

}

【讨论】:

  • 好吧,我问你一件事。如果 Archer 的构造函数需要一个 Game 对象作为参数怎么办?像这样:public Archer(Game game) {}; 因为在这种情况下这将不起作用,因为 Archer 对象是在 Game.java 之前创建的。有什么想法吗?
  • @LawrenceLelo:您上面的问题是一个红鲱鱼问题,因为它与 instanceof 问题无关。简单的解决方案是重写 Archer 的构造函数以允许 Game,但同样,这与您的主要问题无关。
  • 我完全清楚这与我原来的问题无关。但是我提到它是因为我想到了您的解决方案并遇到了这个确切的问题。尽管如此,您的解决方案还是很有帮助的。
  • @LawrenceLelo:我看不出问题出在哪里。您只需为需要将 Game 传递到其构造函数的任何类提供一个允许它的构造函数。我的解决方案不会阻止这种情况,其他解决方案也不会。
  • @LawrenceLelo:不需要一成不变的要求。您可以简单地对一个或两个使用 setter 方法。或者如果你真的想花哨并解耦一切,请使用依赖注入框架,例如 Spring 或 Guice。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-25
  • 2014-07-24
  • 2011-03-09
  • 2012-12-23
相关资源
最近更新 更多