Возможно ли, чтобы данный подкласс инициализировал статические конечные поля в своем суперклассе? По сути, я хотел бы, чтобы подкласс настроил необходимые переменные класса. К сожалению, ключевое слово abstract не работает с полями.
Окончательное наследование полей в java
Ответы (2)
Нет, как бы вы ожидали, что это будет работать, если бы существовало два подкласса, пытающихся сделать одно и то же? Если у вас есть статические конечные поля, они должны быть инициализированы классом, который их объявляет.
Если вы пытаетесь использовать статические поля и наследование вместе, это обычно признак того, что с самого начала что-то не так, честно говоря, это две концепции, которые обычно плохо сочетаются друг с другом. Люди часто пытаются «подделать» наследование с помощью статических методов и т. д., и это обычно плохо заканчивается — это звучит как вариация на эту тему.
Если вы сможете описать свою более широкую картину, мы сможем помочь вам больше. Между прочим, я призываю вас избегать статики вообще ради тестируемости. Они подходят для настоящих констант, но если это что-то вроде конфигурации, лучше передать соответствующие настройки при создании объекта (IMO).
РЕДАКТИРОВАТЬ: я вижу четыре варианта, которые лучше моделируют вашу ситуацию:
- Используйте аннотации: см. ответ True Soft
- Сделайте
maxHealth
методом, чтобы вы могли спросить любого игрока, каково его максимальное здоровье — тогда это полиморфно, поэтому его можно переопределить в каждом классе. Модель
Player
иPlayerClass
отдельно:public class Player { private final PlayerClass playerClass; private int health; // etc } public class PlayerClass { private final int maxHealth; //etc }
Таким образом, вы можете иметь наследование на уровне "класса игрока", но вам это не обязательно - вы можете создать несколько
PlayerClass
экземпляров, которые ведут себя одинаково, но имеют разные характеристики... или вы можете создать подклассPlayerClass
, чтобы задать собственное поведение. В этот момент вам могут вообще не понадобиться разные подклассыPlayer
.То же, что и идея 3, но с использованием перечисления:
public enum PlayerClass { ELF(10), DWARF(9), HUMAN(5); private final int maxHealth; private PlayerClass(int maxHealth) { this.maxHealth = maxHealth; } }
Лично я предпочел бы окончательный вариант, я подозреваю. Вы можете по-прежнему переопределять поведение, но у вас есть фиксированный набор возможных классов, который, вероятно, достаточно точно моделирует вашу игру.
Что касается ответа Джона Скита, я не думаю, что это так уж плохо: «Если вы пытаетесь использовать статические поля и наследование вместе». Я предлагаю вам использовать аннотации:
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface AValue {
/**
* @return something final that is "static" (attached to a class),
* but also "abstract" (looks that it be changed in the subclasses)
*/
String value();
}
@AValue("A default value") // you can ommit this, but all subclasses should add the annotation (so the method from Utils work OK)
abstract class A { }
@AValue("Value for class B")
class B extends A { }
@AValue("Value for class C")
class C extends A { }
class Utils {
static String getValueOfClass(Class<? extends A> clazz) {
return clazz.getAnnotation(AValue.class).value();
}
}