开发者

Takes the variable data from it's own class instead of it's child classes even when called from the child class

Okay, it's been a while, but I'm thinking about getting back into programming.

Anyway, This code takes the variable data from it's own class instead of it's child classes even when called from the child class. How do i get it so it uses the child's variable data instead of it's own when called by the child?

    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";
}


Your code outputs:

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's suggestion outputs:

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's suggestion outputs:

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's suggestion outputs:

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

jitter's suggestion outputs:

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

William's suggestion is exactly the same as adon_y_coya's.

So, it appears that you have no less than five posted answers, consisting of four different ways to do it. And yet you haven't accepted a single answer and you seem to think that this topic is full of trolls and unhelpful. But I think the real problem is that you just don't understand what you're doing, at least in terms of inheritance. You are shadowing your name variable, so that the subclass's name variable and the superclass's name variable are two different variables. You are referencing Combatant.name, which is different from Enemy.name and Player.name, because you are shadowing. That leads me to another possible "solution" for you, although it's just an indicator that you're doing it wrong in the first place.

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!");
}

That approach gives the correct output, but completely eliminates the purpose of class inheritance, obviously. adon_y_coya's suggestion is the correct one, because it is the one that correctly utilizes inheritance.

And don't tell me my suggestion doesn't work. Because, as Joonas Pulakka so cleverly pointed out, twice, the suggestions do work. If you're still finding problems with them then it's because you don't understand Java inheritance well enough - so go find a Java book and read it, because you are not solid enough in your understanding to start messing with inheritance. That's why you've got a -2; people feel that you should probably learn more before you start asking others.


Use getters and setters, and make the properties private


I edited my post, so you can check this again (if you want). I mixed up the names, sorry.

You have to use a constructor in the Combatant class, so you can call your super-class-constructor. Your code has to look like;

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


You can also add constructors in Combatant like:

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

and then you can write this in the Enemy class to make the dragon stronger.

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

Hope this helps.


Fixed.

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

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


I already answered your question in javagaming.org, please check.

I think that in the way you're doing it, you are hiding the parent data member with a child data member, of which the parent has no knowledge, so parent's data member is called instead in parent's method.

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


You already defined the instance variable name in Combatant. Thus Enemy and Player inherit this variable. You don't need to redeclare it. Some of the other answers are also valid and better coding practice. If you don't want to change your code to use either set/get methods or using constructors you can use what are called initializer blocks. The code written in an initializer block is executed by java when an instance of the class is created.

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

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

But be aware that this has some maybe unexpected side effects too. e.g. Consider you declare Enemy2 like this and use it in TestRPG1 instead of Enemy.

public class Enemy2 extends Enemy {
}

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

What do you expect the program to output? null or Dragon as name? It will output Dragon. Why? Because initializer blocks are also executed for child classes constructors.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜