即使从子类调用,也从它自己的类而不是它的子类中获取变量数据

时间:2009-11-22 07:43:27

标签: java

好的,已经有一段时间了,但我正在考虑重新开始编程。

无论如何,即使从子类调用,此代码也会从其自己的类而不是它的子类中获取变量数据。我如何得到它所以当孩子调用时它使用孩子的变量数据而不是它自己的?

    public class TestRPG1 {

        static Player hero;
        static Enemy dragon;

        public static void main(String[] args) {
            hero = new Player();
            dragon = new Enemy();

            while(dragon.hp > 0){
                int choice = (int) (Math.random() * 2);

                if(choice == 0)
                    hero.attack(dragon);

                else
                    hero.magic(dragon); 
            }

            System.exit(0);

        }

    }




    public class Combatant {
        int hp = 100;
        int mp = 100;
        int attack = 15;
        int magic = 25;
        int defence = 15;
        int damage = 0;
        String name = "null";

        public void attack(Combatant target){
            damage = (int) (Math.random() * attack);
            System.out.println(name + " attacked the " + target.name + " for " + damage + " damage!");
            target.hp -= damage;
            System.out.println(target.name + " has " + target.hp + " HP left!");
        }

        public void magic(Combatant target){
            damage = (int) (Math.random() * magic);
            System.out.println(name + " shot a fireball at " + target.name + " for " + damage + " damage!");
            target.hp -= damage;
            System.out.println(target.name + " has " + target.hp + " HP left!");
        }

}


public class Enemy extends Combatant{
    String name = "Dragon";
}


public class Player extends Combatant{
    String name = "Hero";
}

6 个答案:

答案 0 :(得分:2)

您的代码输出:

null shot a fireball at null for 1 damage!
null has 99 HP left!
null attacked the null for 7 damage!
null has 92 HP left!
...etc

adon_y_coya的建议输出:

Hero shot a fireball at Dragon for 15 damage!
Dragon has 85 HP left!
Hero shot a fireball at Dragon for 13 damage!
Dragon has 72 HP left!
...etc

Martijin Courteaux的建议输出:

Hero attacked the Dragon for 5 damage!
Dragon has 95 HP left!
Hero shot a fireball at Dragon for 12 damage!
Dragon has 83 HP left!
...etc

Bozho的建议输出:

Hero shot a fireball at Dragon for 1 damage!
Dragon has 99 HP left!
Hero shot a fireball at Dragon for 3 damage!
Dragon has 96 HP left!
...etc

抖动的建议输出:

Hero shot a fireball at Dragon for 17 damage!
Dragon has 83 HP left!
Hero attacked the Dragon for 14 damage!
Dragon has 69 HP left!
...etc

威廉的建议与adon_y_coya完全相同。

因此,您似乎发布了不少于五个的答案,其中包含四种不同的方式。然而,你还没有接受一个单一的答案,你似乎认为这个话题充满了trolls并且没有帮助。但我认为真正的问题是你只是不明白你在做什么,至少在继承方面。 您是shadowing您的名称变量,因此子类的名称变量和超类的名称变量是两个不同的变量。您正在引用Combatant.name,它与Enemy.name和Player不同.name,因为你是影子。这导致我找到了另一个可能的“解决方案”,虽然这只是一个指示你首先做错了。

public void attack(Combatant target)
{
        damage = (int) (Math.random() * attack);
        System.out.println( ((this instanceof Player) ? ((Player)this).name : ((Enemy)this).name) + " attacked the " + ((target instanceof Player) ? ((Player)target).name : ((Enemy)target).name) + " for " + damage + " damage!");
        target.hp -= damage;
        System.out.println( ((target instanceof Player) ? ((Player)target).name : ((Enemy)target).name) + " has " + target.hp + " HP left!");
}

这种方法提供了正确的输出,但显然完全消除了类继承的目的。 adon_y_coya的建议是正确的,因为它是正确利用继承的建议。

不要告诉我我的建议不起作用。因为,正如Joonas Pulakka巧妙地指出的那样,两次,建议工作。如果你仍然发现它们有问题,那就是因为你不能很好地理解Java继承 - 所以去找一本Java书并阅读它,因为你的理解还不够扎实,不能继续搞乱继承。这就是为什么你有一个-2;在你开始问别人之前,人们觉得你应该学到更多东西。

答案 1 :(得分:0)

使用getters and setters,并将属性设为私有

答案 2 :(得分:0)

我编辑了我的帖子,因此您可以再次查看(如果需要)。 我把名字混淆了,抱歉。

你必须在Combatant类中使用构造函数,因此可以调用你的超类构造函数。你的代码看起来像;

public class Combatant {

    public Combatant(String name)
    {
        this.name = name;
    }

    int hp = 100;
    int mp = 100;
    int attack = 15;
    int magic = 25;
    int defence = 15;
    int damage = 0;
    String name = "null";

    public void attack(Combatant target){
            damage = (int) (Math.random() * attack);
            System.out.println(name + " attacked the " + target.name + " for " + damage + " damage!");
            target.hp -= damage;
            System.out.println(target.name + " has " + target.hp + " HP left!");
    }

    public void magic(Combatant target){
            damage = (int) (Math.random() * magic);
            System.out.println(name + " shot a fireball at " + target.name + " for " + damage + " damage!");
            target.hp -= damage;
            System.out.println(target.name + " has " + target.hp + " HP left!");
    }

}

public class Enemy extends Combatant{
    public Enemy()
    {
        super("Dragon");
    }
}

public class Player extends Combatant{
    public Player()
    {
        super("Hero");
    }
}

<小时/> 您还可以在Combatant中添加构造函数,如:

// A constructor to set the name and change the default magic.
public Combatant(String name, int magic)
{
    this.name = name;
    this.magic = magic;
}

然后你可以在 Enemy 类中写这个来让龙更强壮。

public class Enemy extends Combatant
{
    public Enemy()
    {
        super("Dragon", 30);
    }
}

希望这有帮助。

答案 3 :(得分:0)

固定。

public class Enemy extends Combatant{
    Enemy(){
        name = "Dragon";
    }
}

public class Player extends Combatant{
    Player(){
        name = "Hero";
    }
}

答案 4 :(得分:0)

我已经在javagaming.org上回答了你的问题,请检查。

我认为,按照您的方式,您正在使用子数据成员隐藏父数据成员,父数据库成员不知道,因此在父方法中调用父数据成员。

public class Enemy extends Combatant{
    public Enemy() { name = "Dragon"; }
}
public class Player extends Combatant{
    public Player () { name = "Hero"; }
}

答案 5 :(得分:0)

您已在name中定义了实例变量Combatant。因此EnemyPlayer会继承此变量。您无需重新声明它。其他一些答案也是有效且更好的编码实践。如果您不想更改代码以使用set / get方法或使用构造函数,则可以使用所谓的初始化程序块。初始化程序块中编写的代码在创建类的实例时由java执行。

public class Enemy extends Combatant {
    { name = "Dragon"; }
}

public class Player extends Combatant {
    { name = "Hero"; }
}

但请注意,这也有一些意想不到的副作用。例如您可以考虑像这样声明Enemy2并在TestRPG1而不是Enemy中使用它。

public class Enemy2 extends Enemy {
}

....
dragon = new Enemy2();
....

您希望程序输出什么? nullDragon作为名称?它将输出Dragon。为什么?因为初始化程序块也是为子类构造函数执行的。