Java: ArrayList в суперклассе

1

У меня ужасное время с использованием ArrayList в суперклассе. ArrayList используется для хранения объектов трех разных типов подклассов суперкласса Enemy. В зависимости от того, как я ссылаюсь на объект в ArrayList в файле драйвера, он диктует разные результаты.

Враг - это ребенок суперкласса, который называется бойцом. Истребитель хранит личные данные для всех объектов.

Вот супермарк Enemy.

import java.util.*;

public class Enemy extends Fighter {
    public void getRandomEnemy(){};
    public ArrayList<Enemy> enemy = new ArrayList<Enemy>();

    Enemy(String wep, String arm, String nam, int health, int magResis, int physResis, int rangResis)
    {
        super(wep,arm,nam,health,magResis, physResis,rangResis);
    }
}

Например:

Два подкласса Enemy Troll и Sorcerer имеют объекты соответствующих типов, добавленные в ArrayList, найденные в родительском классе Enemy.

Конструкторы троллей и колдунов:

Sorcerer(String wep, String arm, String nam, int health, int magResis, int physResis, int rangResis)
    {
        super(wep,arm,nam,health,magResis, physResis,rangResis);
    }

Troll(String wep, String arm, String nam, int health, int magResis, int physResis, int rangResis)
    {
        super(wep,arm,nam,health,magResis, physResis,rangResis);
    }

Этими методами я добавляю объекты в ArrayList в суперклассе противника. Каждый метод находится в соответствующем классе.

public void getRandomEnemy()
    {
        enemy.add(new Troll("Bow", "Leather", "Troll",350, 30, 15,30));
    }

public void getRandomEnemy()
    {
        enemy.add(new Sorcerer("Staff", "Cloth", "Sorcerer",300, 70, 5,5));

    }

Теперь в моем файле драйвера, если я добавлю объекты типов троллей и колдунов в ArrayList в качестве врага.

Файл драйвера:

int p = 5; // adds 5 enemies to the ArrayList enemy
int randEnemy = 0;
        for(int i =0; i < p; ++i)
        {

            randEnemy = (int) (Math.random() * (3));

            if(randEnemy == 0)
            {
                sorc.getRandomEnemy();
            }
            else if(randEnemy == 1)
            {
                trol.getRandomEnemy();
            }
            else
            {
                og.getRandomEnemy();
            }
        }

Здесь я начинаю сталкиваться с проблемами. Например, если я хочу вернуть размер врага ArrayList. Общий размер, который я должен сделать в файле драйвера.

int size = sorc.enemy.size() + trol.enemy.size() + og.enemy.size();

Я должен вызывать каждый конкретный тип объекта и добавлять их вместе.

Если я делаю Enemy.enemy.size(); Он вернет 0.

Опять же, все становится подозрительным с ArrayList, когда я хочу атаковать врага. Мне нужно специально искать каждый объект Sorc или объект Troll в ArrayList.

for(Enemy j : sorc.enemy)
                {   
                    System.out.println("Sorc Health: " + j.getHealth());
                    System.out.println("Sorc Armor: "+ j.getArmor());
                    sorc.takeDamage(attack, "Cloth", weapon);
                }

Если я сделаю код выше, я получу правильное здоровье для Волшебника, которому будет 300, и я получу правильную броню. Но Волшебник не получит никакого урона.

Если я это сделаю:

for(Enemy j : sorc.enemy)
                {   
                    System.out.println("Sorc Health: " + j.getHealth());
                    System.out.println("Sorc Armor: "+ j.getArmor());
                    j.takeDamage(attack, "Cloth", weapon);
                }

Здоровье вернет -1999234 или некоторое случайное отрицательное значение, но метод takeDamage() будет работать отлично.

Мой вопрос: почему, когда я ссылаюсь на объект по-другому, у меня разные результаты? Как правильно ссылаться на объекты в ArrayList, чтобы убедиться, что установлены правильные значения? Я уверен, что это не логическая ошибка, потому что я устанавливаю значения в конструкторах и вызываю конструкторы метода getRandomEnemy() для добавления объектов в ArrayList.

EDIT: проблема исправлена

В суперблоке Fighter конструктор определяется как таковой.

public Fighter(String wep, String arm, String nam, int health, int magResis, int physResis, int rangResis)
    {
        this.name = nam;
        this.weapon = wep;
        this.armor = arm;
        this.health = health;
        this.magicResistance = magResis;
        this.physicalResistance = physResis;
        this.rangedResistance = rangResis;
    }

Здоровье давало мне проблему. Это была единственная переменная, которая выворачивала неуловимые данные. Как видите, параметр имеет int health, и я устанавливаю этот аргумент, который передается this.health = health;

Хотя я использую это. чтобы различать параметр и переменную экземпляра, значение оказывалось отрицательным.

Я просто сменил конструктор на это:

public Fighter(String wep, String arm, String nam, int hea, int magResis, int physResis, int rangResis)
    {
        this.name = nam;
        this.weapon = wep;
        this.armor = arm;
        this.health = hea;
        this.magicResistance = magResis;
        this.physicalResistance = physResis;
        this.rangedResistance = rangResis;
    }

и теперь все работает.

  • 4
    Пожалуйста, покажите короткую, но полную программу, демонстрирующую проблему - вы еще не предоставили достаточно информации, чтобы мы могли вам помочь.
  • 0
    @Jon Skeet Хорошо, я в этом! Прости за это!
Показать ещё 26 комментариев
Теги:
arraylist

1 ответ

5
Лучший ответ

Я думаю, что ваша проблема - непонимание того, как работают члены суперкласса.
Когда вы объявили:

public class Enemy extends Fighter {
    public ArrayList<Enemy> enemy = new ArrayList<Enemy>();
}

Каждый объект типа Enemy или подкласс Enemy будет иметь свой собственный экземпляр списка enemy. Они не будут использовать один и тот же список.
Также вы смешиваете разные объекты:

Sourcerer sourcer = new Sourcerer();
sourcer.getHealth(); // this is a member of the object just created;
sourcer.enemy;  // is a list of Enemy type objects
                // this list is a member of the sourcer object

for(Enemy enemy : sourcer.enemy) {
      enemy; //is an object in the list
            //this object should not be sourcer object (see below)
}

sourcer.enemy.add(sourcer); //is valid but will make a really big mess
                            //so make sure you never do this. 

Если вы хотите, чтобы ваши объекты использовали один и тот же список из суперкласса, вам нужно объявить его static.
Я бы посоветовал вам создать отдельный класс, который управляет битвой и имеет список. Таким образом вы отделяете отдельных персонажей (бойцов, врагов, колдунов, троллей) от управления группами персонажей (битвы).

  • 0
    Я вижу, что вы говорите, и спасибо за вашу помощь. Но есть ли какая-то причина, почему в зависимости от того, как я ссылался на ArrayList, результаты были разными или почему устанавливаются значения?
  • 1
    @ TheDude1142 Добавьте некоторые временные распечатки отладки к вашим различным методам или, что еще лучше, пошагово проходите по одной строке в отладчике (если вы используете, например, Eclipse или NetBeans). Это позволит вам точно следить за тем, что происходит в обоих случаях. Совет: Дайте каждому из ваших объектов уникальное имя и напечатайте его (или, по крайней мере, this.getClass().getSimpleName() ) в ваших распечатках трассировки, чтобы помочь вам определить, что вызывается для чего.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню