2014-12-08 4 views
1

Мне нужно иметь статическую переменную, не связанную с объектом, а с самим классом. Однако переменная также не должна быть связана с родительским классом или всеми другими подклассами, которые расширяют один и тот же родительский класс.статическая переменная в подклассе Java

скажем:

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

Возможно ли это? Или мне нужно объявить статическую переменную в каждом подклассе? Я попытался, и когда я попытался получить доступ к статической переменной, значение статической переменной оказалось одинаковым для каждого класса.

+1

«каждый объект Warrior будет иметь значение атаки 50» Неверно, статическая переменная не принадлежит объекту – JamesB

+5

Статическая переменная разделяет значение с каждым объектом класса, который его объявляет. Поэтому каждый подкласс будет иметь и это значение. Если основной класс или другой подкласс изменить это значение, каждый класс (независимо от родителя или подкласса) будет иметь новое значение. Итак, да, вам нужно объявить новую статическую переменную для каждого подкласса. – BackSlash

+1

Возможный дубликат [Java - Начать статическое поле и изменить его значение] (http://stackoverflow.com/questions/16202884/java-inherit-static-field-and-change-its-value) –

ответ

2

Нет, это невозможно. Родительский класс ничего не знает о статических или нестатических членах в своих подклассах.

Однако код, который вы опубликовали, говорит мне, что вы хотите переопределить статическую переменную. Это также невозможно, могут использоваться только нестатические методы (если у них есть соответствующий уровень доступа).

4

Ваш текущий код не будет делать то, что вы хотите, так как существует только одна переменная attack в классе Army, и она может иметь только одно значение.

Вы могли бы иметь метод в армии, которая возвращает значение по умолчанию:

public int getAttack() 
{ 
    return 10; 
} 

Затем вы можете переопределить этот метод в своих суб классы:

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

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

Даже если getAttack() не является переменной, и он не является статичным, он по-прежнему удовлетворяет вашим требованиям - каждый подкласс может иметь другое значение, разделяемое всеми экземплярами этого подкласса.

0

Статическая переменная инициализируется, когда класс сначала загружается загрузчиком классов.

Сбрасывая переменную атаки, вы пытаетесь создать экземпляр, например, Warrior. Поэтому перед использованием Warrior.attack сделать следующее:

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

Я бы сказал, что нужно создать метод getAttack в классе армии и пусть воин и другое переопределение его. Что-то вроде:

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

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

Свойство атаки не должно быть статичным, и вы должны определить каждый класс.
Но подумайте об использовании перечисления.

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

Для констант это могло бы работать (хотя перечисление должно быть расширено с помощью int attackValue). В тот момент, когда он пытается загрузить эти значения из внешнего файла, хотя это будет разваливаться. – Joeblade

0

В идеальном мире вы могли бы сделать что-то вроде:

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

К сожалению, Java не позволяет этого.

Ближайший вы можете получить будет что-то вроде:

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

Это будет возможно сделать так, как вы пытаетесь сделать.

Что вы хотите достичь - это иметь переменную static в базовом классе и затем иметь разные значения одной и той же переменной для каждого из ее подклассов.

Как это статическая переменная, поэтому она будет иметь одинаковое значение для всех объектов. Он не может иметь одно значение для одного подкласса и другое значение для другого подкласса. Поскольку это одна общая статическая переменная для обоих классов. Итак, какова бы ни была его ценность, будет распространяться и для дочерних классов.

Что вы можете сделать, это иметь статические переменные в каждом дочернем классе, то есть Warrior, имеющем собственную статическую переменную и Archer с собственной статической переменной.

0

Я предполагаю, что на ваш прямой вопрос (может быть наследуется статический) был дан ответ. Я подумал, что предлагаю альтернативный подход:

С вашего вопроса я предполагаю, что вы хотите не добавлять 4 байта в каждый экземпляр с их уникальным значением атаки, так как каждый воин имеет 50 атак, это должно быть 1 место, которое перечисляет это , Это решение по-прежнему будет стоить 4 байта в случае 1 номера, но будет более оптимальным в случае более чем 1 из этих чисел.

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

Конечно, это не идеальный (синглтон может и не быть тем, чего вы хотите). Эта настройка позволит вам загружать конфигурацию с диска без необходимости перекомпилировать файлы. (во время конструктора ConfigFactory загрузите файл с диска, проанализируйте его и создайте экземпляры)

Таким образом вы разделяете фактические настройки/конфигурацию объектов по логике, которым нужны эти объекты. Для мелкомасштабных вещей, hardcoding - это вариант, для больших проектов, которые вы, возможно, захотите извлечь.

Смежные вопросы