没有为扩展类中的变量获取正确的值

时间:2011-11-11 12:39:35

标签: java class inheritance polymorphism extend

只需在我的帖子顶部进行快速编辑即可。 问题是如果我扩展一个类并且两个类都具有相同的变量,为什么扩展类获得原始类值。

已经回答了这个问题,但我们非常乐意阅读有关此内容的更多信息。 多态性不是我的强项,所以我不得不在几个月没有使用它之后重新学习这些东西。

所以我正在尝试编写一个游戏,其中一个要求是可以循环扫描的某种类型的对象列表。麻烦从我对ArrayList的测试开始。我有三个类,我被添加到我的数组列表中。实体,Monster扩展实体,Character扩展实体。请注意Monster和Character都扩展了Entities类。 我决定我应该创建ArrayList并将新对象直接添加到每个元素中(word元素通常与数组一起使用而不是ArrayList正确吗?)并使用我编程的日志函数来记下ArrayList中对象的值。 我做了一个for循环并运行了他们从Entities继承的Monster和Character .getHP()方法,结果是来自Entities not Monster或Character的HP,除非我使用setHP(int i)向HP类添加了一个新值方法也继承了实体。

由于我的程序需要大多数类,我们只需要大约99%我决定制作一个测试项目,基本上以较小的形式执行上述操作,因为我不想复制粘贴20个或更多.java文件这里。无论如何,这是我的测试课程和成绩。

    import java.util.ArrayList;

    // class to test interactions between Extended classes
    public class testHP {
        ArrayList<Entities> ent = new ArrayList<Entities>();

        public static void main(String[] args) {

            ///make reference varaible so i don't have to make test() and ent static. 
            testHP hp = new testHP();
            hp.test();
        }
        void test(){
            /// the 3 classes to the arraylist. I could of made a reference variable but didn't.
            this.ent.add(new Character());
            this.ent.add(new Monster());
            this.ent.add(new NPC());
            ///prints out whats in the array list so i know that i have the correct objects.
            System.out.println(this.ent);

            /// this prints out { ent(i) HP "is" i } to tell which class is being called and it's HP at this point.
            for(int i=0; i<ent.size();i=i+1) {System.out.println(this.ent.get(i).getHP() +" is "+ this.ent.get(i));}
            /// this adds i plus 10 then does the same as the last for loop.
            for(int i=0; i<ent.size();i=i+1) {
                this.ent.get(i).gainHP(i+10);
                System.out.println(this.ent.get(i).getHP() +" is "+ this.ent.get(i));}
        }
    }



abstract public class Entities {
    private int HP = 1;

    int getHP(){
        return HP;
    }
    void gainHP(int hp){
        HP = this.HP + hp;
    }
}



///Character is to show what happens when i change the value and make it static.
public class Character extends Entities {
    private static int HP = 4;
}


///monster is to show a changed variable from the super which is entities.
public class Monster extends Entities {
    private int HP = 4;

}

/// NPC is a class that just to have variables from entities class that aren't edited or made static. 
public class NPC extends Entities {

}

这是我在上面的这些文件的结果。我应该把HP放在左边的数字旁边,但你明白了。

[Character@67f1fba0, Monster@3fbefab0, NPC@133c5982]
1 is Character@67f1fba0
1 is Monster@3fbefab0
1 is NPC@133c5982
11 is Character@67f1fba0
12 is Monster@3fbefab0
13 is NPC@133c5982

原始ArrayList的测试类看起来像这样。

import java.util.ArrayList;
public class AreaMap extends Map {


    String CLASS = "Area Map";///log requires.
    ArrayList<Entities> ent = new ArrayList<Entities>();    
    AreaMap(){
        Log.Logging(CLASS,"Testing arrayList");

        //random text added to the array.
        ent.add(new Character());
        ent.add(new Monster());
        Log.Logging(CLASS, "ent 1 has " +ent+ " in it");
        for(int i=0; i < ent.size();i = i+1){
        Log.Logging(CLASS, "ArrayList " + this.ent.get(i).getHealth() +" i="+i);
        }
        for(int i=0; i < ent.size();i = i+1){
            this.ent.get(i).setHP(10+i);
        Log.Logging(CLASS, "ArrayList " + this.ent.get(i).getHealth() +" i="+i);
        }
    }
}

这是我的结果。

[Area Map]##[Testing arrayList]
[Area Map]##[ent 1 has [Character@2bd1e730, Monster@61a116c9] in it]
[Area Map]##[ArrayList 0 i=0]
[Area Map]##[ArrayList 0 i=1]
[Area Map]##[ArrayList 10 i=0]
[Area Map]##[ArrayList 11 i=1]

请注意,“Log”是我制作的类,方法是“静态日志记录(String origin,String Action){System.out.println([origin] +”##“+ [Action]);” 起源总是不是必须的阶级。

对不起,如果不清楚的话。如果您需要更多信息来帮助我,我非常愿意回答。

3 个答案:

答案 0 :(得分:2)

基本上问题是你试图在子类中声明额外的变量,好像它们可以“覆盖”超类中的变量一样。变量不起作用 - 它们不是多态的。

如果您需要为每个班级提供不同的起始点数,我建议您在protected中创建一个Entities构造函数(应该重命名,顺便说一下 - 例如AbstractEntity)取HP的初始值(可能应该重命名为hitPoints)。然后每个子类都有一个公共构造函数来调用具有适当值的超构造函数。

例如:

public abstract class AbstractEntity {
    private int hitPoints;

    protected AbstractEntity(int initialHitPoints) {
        this.hitPoints = initialHitPoints;
    }

    public int getHitPoints(){
        return hitPoints
    }

    void gainHitPoints(int amount) {
        hitPoints += amount;
    }
}

public class Monster extends AbstractEntity {
    public Monster() {
        // Every monster starts off with 4 hit points
        super(4);
    }
}

现在这只是改变初始状态的问题。如果您希望不同的实体行为不同,则应覆盖子类中的抽象类方法。

答案 1 :(得分:0)

我相信你的问题是范围界定。可以从HP访问Entities *的getHP,但HPCharacter中的Monster是碰巧拥有一样的名字。此外,将HP标记为private表示子类无法访问该变量 - 我认为您已protected

在Monster和Character中摆脱HP的正确解决方案是什么,使实体中的HP受到保护,并在Monster和Character的默认构造函数中设置默认HP。

*以单数形式命名对象是一种很好的风格,因此最好将其命名为Entity

答案 2 :(得分:0)

如果我理解正确,问题如下:

您在类Entities中将属性HP声明为私有,并在子类中声明了一个新的(!)变量(请参阅其他答案)。

您可以通过构造函数设置HP来解决此问题,例如: g。,

class Entitites {
  private int HP;

  public Entities(int hp) {
    this.HP = hp;
  }
}

class Monster extends Entities {
  public Monster() {
    super(4);
  }
}