1

Recently I asked a question about why all my variables in spawned items were being set to the same damage value (Java switch statements outputting the same numbers) and that code wasn't to blame, however after some deep debugging i've found that when an item is spawned it randomises the damage and then for some reason sets that damage to every previously created item of the same type.

I have 'dagger' and 'sword' classes which extend my 'item' class. This is how I set the damage:

case 3: {Sword sword = new Sword(); World[X][Y].treasureName = "sword"; sword.setDamage(4); returnItem = sword; break;}

And this is my item class:

public abstract class Item {
//How much damage is added to the players attack.
static int damage = 0;
static int defence = 0;

public int getDefence() {
    return defence;
}

public void setDefence(int defenceValue) {
    defence = defenceValue;
}

public int getDamage() {
    return damage;
}

public void setDamage(int damageValue) {
    damage = damageValue;
}
}

And my sword class:

public class Sword extends Item { 
//How much damage is added to the players attack.
static int damage = 0;
static int defence = 0;

public int getDefence() {
    return defence;
}

public void setDefence(int defenceValue) {
 defence = defenceValue;
}

public int getDamage() {
    return damage;
}

public void setDamage(int damageValue) {
    damage = damageValue;
}
}

I'm not sure what this problem is called and not sure what to google being fairly new still. I tried to override the item class but that didn't change anything and i've read about inheritance and I don't understand which part is setting every other weapon instance to the same damage. I wanted to remove the methods in the 'Item' class to see if that would fix it, however other code causing errors prevented me to do this when checking and adding together the damage of all the children of 'Item' - this required a cast of (Item) and i'm not sure of what else I can use as a cast.

Here are the referrals to the 'Item' method:

if (((Item) World[k][i].treasure).getDamage() > 9)
                            {

Without the cast the error is: getDamage() is undefined for the type Object. and:

//Recalculates the players damage for recently equipped items.
        for (int i = 0; i < numItems; i++) {
            itemdamage += items[i].getDamage();
            System.out.println("You have a " + itemNames[i] + " giving you " + items[i].getDamage() + " extra damage.");
            }

What's wrong? I want to understand this so links to helpful information on why, and what i'm doing wrong would be good. Thanks.

Community
  • 1
  • 1

5 Answers5

5
static int damage = 0;

Having a static member means that all objects of the class same the same value. If you remove the static keyword, each object will be able to have a different value for damage.

As to the required cast, it seems that World is an array of Object type. Therefore World[k][i] is of Object type, and you can only call methods of the base Object class on it. If you want to call a method defined in the Item class, you must cast the Object to an Item (assuming the runtime type of that Object is an Item).

Eran
  • 387,369
  • 54
  • 702
  • 768
4

Your damage and defense variables should not be static. A static variable is tied to the whole class, not to any one instance of the class. As such, when you call setDamage(), even though the method is an instance method, it updates a static variable which is shared by every existing instance.

Remove the static (did you mean to use protected?) and you won't see the "for some reason sets that damage to every previously created item of the same type" behavior anymore.

See What does the 'static' keyword do in a class? for more. Here's the official Java Language Specification on static fields, as well.

Community
  • 1
  • 1
dimo414
  • 47,227
  • 18
  • 148
  • 244
2

You set the variables damage and defence (spelling mistake here - by the way) to be static. Which means that there's only one copy of each variables for the entire class.

Remove the static keyword before the declaration of both variables - and it'll make any new sword instance (object) - carry its own damage and defence.

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
  • Oh I must have somehow missed that while reading through the material :s - Also i'm Australian and that's how we spell Defense. :p – Fluidic Ice Apr 16 '15 at 05:43
  • @FluidicIce then I definitely shouldn't try to correct your English (since it's *not* my mother tongue :) – Nir Alfasi Apr 16 '15 at 05:47
2

Heyhey Fluidic,

I'm still fairly new to Java myself, but I think your problem is that your damage variables are set to static (and I would assume the problem would persist across your defence stats as well!)

I had this problem while learning to develop in C++. I would change a value of one of my constructors which referenced a static variable, and all of the instances would change. It's a constant belonging to the class itself, not the object.

So what's happening, is when you change the damage value; all references that use that static damage variable are being changed.

This site gives a bit of an insight on static variables! http://www.javatpoint.com/static-keyword-in-java

Lemme know if that helps!

Andy

Andy Ruiz
  • 29
  • 4
  • Ah yes, thanks for that, it was indeed the problem, (but someone beat you to it :p) Now I know, I used GM before java so I understand it basically as a 'global' variable now. Thanks for the comment. – Fluidic Ice Apr 16 '15 at 05:57
1

According to the error :

getDamage() is undefined for the type Object

I think you World array, is an array of Object instead of Item

Could you show us how you manage the World array ?

Vyncent
  • 1,185
  • 7
  • 17
  • This was something else I was confused about, Actually the World array is set up like: static MapSquare[][] World = new MapSquare[mapSizeX][mapSizeY]; The mapsquare object has a variable: 'Treasure' which stores the loot in this room. So I should be able to call World[x][y].treasure.getDamage(); To get the damage from the item on the square. – Fluidic Ice Apr 16 '15 at 05:48
  • Does Treasure extends Item ? – Vyncent Apr 16 '15 at 06:36
  • No it doesn't, treasure is just a variable. – Fluidic Ice Apr 16 '15 at 06:52
  • Initialized by: World[x][y].treasure = So what type would it be if I did that? – Fluidic Ice Apr 16 '15 at 06:59