static variable in subclass Java

2019-07-06 11:18发布

问题:

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.

回答1:

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).



回答2:

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.



回答3:

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


回答4:

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


回答5:

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.



回答6:

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


回答7:

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.



标签: java oop object