6

I need to have a static variable that is not related to an object, but to the class itself. However, the variable must also not be related to the parent class, or all other sub-classes that extends the same parent class.

let's say:

    class Army{
      static int attack = 0;
    }

    class Warrior extends Army{
      public Warrior(){ 
        attack = 50;   // every Warrior object will have attack value of 50
      }
    }

    class Archer extends Army{
       public Archer(){ 
         attack = 75; // every Archer object will have attack value of 75
       }
    }

Is it possible? Or do I need to declare the static variable in each subclass? I've tried and when I tried to access the static variable, the static variable's value ended up the same for every class.

5
  • 2
    "every Warrior object will have attack value of 50" Not true, the static variable does not belong to an object Commented Dec 8, 2014 at 9:36
  • 5
    A static variable shares the value with every object of the class that declares it. So every subclass will have that value too. If the main class or other subclass change that value, every class (no matter if parent or subclass) will have the new value. So yes, you need to declare a new static variable for each subclass. Commented Dec 8, 2014 at 9:36
  • 1
    possible duplicate of Java - Inherit static field and change it's value Commented Dec 8, 2014 at 9:37
  • 1
    you need to declare a new static variable for each subclass. Commented Dec 8, 2014 at 9:39
  • Why is this a static variable? Commented Dec 8, 2014 at 13:56

7 Answers 7

10

Your current code won't do what you want, since there is only one attack variable in Army class, and it can have only one value.

You could have a method in Army that returns a default value :

public int getAttack()
{
    return 10;
}

Then you can override this method in your sub classes :

class Warrior extends Army
{
    ...
    @Override
    public int getAttack()
    {
        return 50;
    }
    ...
}

class Archer extends Army
{
    ...
    @Override
    public int getAttack()
    {
        return 75;
    }
    ...
}

Even though getAttack() is not a variable, and it's not static, it still fulfills your requirements - each sub-class can have a different value shared by all instances of that sub-class.

Sign up to request clarification or add additional context in comments.

Comments

5

No it's not possible. The parent class knows nothing about static or non-static members in it's subclasses.

However the code you've posted tells me you want to override a static variable. It's not possible either, only non-static methods can be overriden (if they have the appropriate access level).

Comments

1

The attack property must not be static, and you must define it every class.
But consider using enum.

public enum Attack {
    Army,
    Warrior,
    Archer; 
}

.

public class Army {
    private final Attack attack = Attack.Army;
}

.

public class Warrior extends Army{
    private final Attack attack = Attack.Warrior;
}

.

public class Archer extends Army{
    private final Attack attack = Attack.Archer;
}

1 Comment

For constants this would work (though the enum would need to be extended with int attackValue). The moment he tries to load these values from an external file though this will fall apart.
0

Static variable is initialized when class is first loaded by classloader.

You are resetting the attack variable when you try to create instance of say Warrior. So before using Warrior.attack do the following:

new Warrior();
System.out.println(Warrior.attack);//output would be 50

I would say that you create a getAttack method in your Army class and let Warrior and other override it. Something like:

class Army{
  public int getAttack() {
      return 0;
  }
}

class Warrior extends Army{
  public int getAttack() {
      return 50;
  }
}

Comments

0

It won't be possible to do so the way you are trying to do.

What you want to achieve is, have a static variable in base class and then have different values of the same variable for each of its sub class.

As it is static variable, so it will have same value for all the objects. It can't have one value for one sub class and other value for other sub class. As it is one common static variable for both the classes. So what ever its value is, will be common for both the child classes.

What you can do is have static variables in each child class i.e. Warrior having its own static variable and Archer having its own static variable.

Comments

0

In a perfect world you would do something like:

abstract class Army {
    // Final to make sure it is filled in - abstract to postpoone that to sub-classes.
    // NB: NOT valid Java.
    abstract final int attack;
}

Unfortunately Java does not allow that.

The closest you can get would be something like:

class Army {

    // Final to make sure it is filled in.
    final int attack;

    // Forces subclassses to use super(attack).
    public Army(int attack) {
        this.attack = attack;
    }
}

class Warrior extends Army {

    public Warrior() {
        // I get an error if I don't do this.
        super(50);
    }
}

Comments

0

I'm assuming your direct question (can static be inherited) has been answered. I thought I'd suggest an alternate approach:

From your question I assume you want to avoid adding 4 bytes to each instance with their unique attackvalue, as each warrior has 50 attack, it should be 1 place that lists this. This solution will still cost 4 bytes in case of 1 number but will be more optimal in the case of more than 1 of these numbers.

class Army {
    private final ArmyConfiguration configuration;
    public Army() {
        this("Army");
    }
    public Army(String configurationName) {
        this.configuration = ConfigFactory.getInstance().getConfiguration(configurationName)
    }

    public ArmyConfiguration getArmyConfiguration() { return configuration; }
}

class Warrior {
    super("Warrior");
}

class Archer {
    super("Archer");
}

class ConfigFactory {
    private static ConfigFactory instance;

    public synchronized ConfigFactory getInstance() {
        if (instance == null) {
            instance = new ConfigFactory();
        }
        return instance;
    }

    private Map<Class, ArmyConfiguration> configMap;

    public ConfigFactory() {
        this.configMap = new HashMap<Class, ArmyConfiguration>();
        configMap.put("Army", new ArmyConfiguration(0));
        configMap.put("Warrior", new ArmyConfiguration(50));
        configMap.put("Archer", new ArmyConfiguration(75));
    }

    public ArmyConfiguration getConfiguration(String name) {
        return configMap.get(name);
    }
}

class ArmyConfiguration {
    public final int attackValue;

    public ArmyConfiguration(final int attackValue) {
        this.attackValue = attackValue;
    }
}

Ofcourse this isn't ideal (singleton might not be what you want). This setup would let you load the config from disk without havign to recompile things. (during the ConfigFactory constructor, load file from disk, parse it and construct the instances)

This way you separate the actual settings / configuration of the objects from the logic those objects need. For smallscale stuff, hardcoding is an option, for larger projects you may want to extract.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.