2016-06-10 2 views
2

Я использую Java instanceof, но он, похоже, не работает.Почему «экземпляр» не работает?

У меня есть три классы java, которые расширяют класс Hero.
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, код предназначен для проверки chosenHero является ли объект Archer.java, Warrior.java или Mage.java, но результат: «Вы выбрали НИЧЕГО». Почему instanceof не может проверить, присвоен ли я уже Archer.java на приветственном экране?

+2

лучник переменная равна нулю. - где вы называете 'new Archer()' где угодно? –

+0

Вам нужно научиться использовать отладчик, а затем использовать его. Также большое использование 'instanceof' - это структура, которая выделяет запах кода и ее следует избегать. –

+1

@HovercraftFullOfEels umm ... ладно ... Как это пахнет? – RobotKarel314

ответ

2

Потому что ваши константы 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”?

+0

Почему вы думаете, что они должны быть статическими? – shmosel

+0

@shmosel, потому что они кажутся глобальными типами символов для какой-то RPG (наличие четырех полей «Hero» для одного игрока кажется немного странным). В качестве альтернативы, они должны быть полностью исключены, и у op может быть только одно поле «Герой героя» («Hero hero = new Archer();») –

+0

Я подозреваю, что «герой» должен быть переменной экземпляра 'WelcomeScreen' и предыдущие типы были связаны с тем, что OP не понимал, как назначать новые экземпляры. – shmosel

2

Альтернативное решение: избавиться от InstanceOf, как это предполагает хрупкий жесткую конструкцию, тот, который легко ломаются. Вместо этого попробуйте использовать другие более совместимые с ООП решения, такие как наследование или сложный шаблон шаблона посетителей.

Например, простая структура наследования может выглядеть примерно так:

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

} 
+0

Хорошо, позвольте мне кое-что спросить. Что, если конструктору Арчера нужен объект «Игра» в качестве параметра? Например: ** public Archer (Game game) {}; ** Потому что в этом случае это не будет работать, поскольку объект Archer создается до Game.java. Есть предположения? – Dragneel

+0

@LawrenceLelo: ваш вопрос выше - вопрос с красной серой, поскольку он не имеет ничего общего с проблемой instanceof. Простым решением было бы переписать конструктор Арчера, чтобы позволить Game, но опять же, это не имеет ничего общего с вашей основной проблемой. –

+0

Я полностью осознаю, что это не имеет ничего общего с моей оригинальной проблемой. Но я упоминаю это, потому что я думал о вашем решении и столкнулся с этой точной проблемой. Тем не менее, ваше решение очень полезно. – Dragneel

Смежные вопросы