【问题标题】:Java: ArrayList in SuperclassJava:超类中的 ArrayList
【发布时间】:2015-03-30 13:33:09
【问题描述】:

我在超类中使用 ArrayList 时感觉很糟糕。 ArrayList 用于保存超类 Enemy 的三种不同类型的子类的对象。根据我在驱动程序文件中引用 ArrayList 对象的方式,会产生不同的结果。

敌人是一个叫做战士的超类的孩子。 Fighter 拥有所有对象的私有数据。

这里是超类 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 将各自类型的对象添加到父类 Enemy 中的 ArrayList 中。

巨魔和巫师构造函数:

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

    }

现在在我的驱动程序文件中,如果我将 troll 和 sorcerer 类型的对象添加到敌人的 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 会变得很可疑。我必须专门寻找 ArrayList 中的每个 Sorc 对象或 Troll 对象。

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

如果我执行上面的代码,我将获得正确的巫师生命值 300,并且我将获得正确的盔甲。但是,巫师不会受到任何伤害。

如果我这样做:

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

生命值会返回 -1999234 或一些随机的负值,但 takeDamage() 方法会完美运行。

我的问题是为什么当我以不同的方式引用对象时,会得到不同的结果?如何正确引用 ArrayList 中的对象以确保设置正确的值?我确信这不是逻辑错误,因为我在构造函数中设置值并在 getRandomEnemy() 方法中调用构造函数以将对象添加到 ArrayList。

编辑:问题已修复

在超类 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;
    }

现在一切正常。

【问题讨论】:

  • 请展示一个简短但完整的程序来说明问题 - 您还没有提供足够的信息让我们帮助您。
  • 请提供 Troll 的构造函数。
  • 发布实际程序的 sn-ps 存在两个问题,而不是显示问题的简短但完整的程序:您将不断收到更多片段的请求,并且您错过了有机会通过查看重现它所需的内容来自己找到错误。
  • @JasonC 我很抱歉,我正在努力。我会更详细地制作一个简短的程序。
  • @JasonC 你说得对,我问的问题不够具体。我感谢大家对我很好,尽管这个问题搞砸了。我会尝试修复它。我想我只是对什么决定了一个简短而完整的程序感到困惑。足够短,你们都可以运行它吗?我假设是这样,我会修复它。

标签: java arraylist


【解决方案1】:

我认为您的问题是对超类成员如何工作的误解。
当你声明:

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
我建议您创建一个单独的类来管理战斗并将列表放在那里。通过这种方式,您可以将单个角色(战士、敌人、巫师、巨魔)与角色组(战斗)的管理分开。

【讨论】:

  • 我明白你在说什么,感谢你的帮助。但是,根据我引用 ArrayList 的方式,结果会有所不同,或者为什么要设置这些值,有什么原因吗?
  • @TheDude1142 将一些临时调试打印输出添加到您的各种方法中,或者更好的是,在调试器中一次执行一行(如果您使用的是 Eclipse 或 NetBeans)。这将让您准确了解两种情况下发生的情况。提示:给每个对象一个唯一的名称并在跟踪打印输出中打印它(或至少this.getClass().getSimpleName()),以帮助您识别在什么上调用了什么。
  • @JasonC 你就是 JasonC。我每天都学得越来越多。
  • 我扩展了答案以澄清为什么您会看到不同的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-18
  • 1970-01-01
  • 1970-01-01
  • 2014-06-13
  • 2018-05-16
  • 2010-12-01
  • 1970-01-01
相关资源
最近更新 更多