У меня ужасное время с использованием 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;
}
и теперь все работает.
Я думаю, что ваша проблема - непонимание того, как работают члены суперкласса.
Когда вы объявили:
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
.
Я бы посоветовал вам создать отдельный класс, который управляет битвой и имеет список. Таким образом вы отделяете отдельных персонажей (бойцов, врагов, колдунов, троллей) от управления группами персонажей (битвы).
this.getClass().getSimpleName()
) в ваших распечатках трассировки, чтобы помочь вам определить, что вызывается для чего.