Окончательное наследование полей в java

Возможно ли, чтобы данный подкласс инициализировал статические конечные поля в своем суперклассе? По сути, я хотел бы, чтобы подкласс настроил необходимые переменные класса. К сожалению, ключевое слово abstract не работает с полями.


person lowq    schedule 21.10.2011    source источник
comment
статические поля??? наследование???   -  person Prince John Wesley    schedule 21.10.2011
comment
Думаю, я просто хотел бы избежать дублирования кода, требуя, чтобы подклассы объявляли заданные поля. Эти переменные не должны выделяться для каждого экземпляра, потому что в данном случае это не имеет смысла (maxHealth, maxEnergy и т. д.).   -  person lowq    schedule 21.10.2011


Ответы (2)


Нет, как бы вы ожидали, что это будет работать, если бы существовало два подкласса, пытающихся сделать одно и то же? Если у вас есть статические конечные поля, они должны быть инициализированы классом, который их объявляет.

Если вы пытаетесь использовать статические поля и наследование вместе, это обычно признак того, что с самого начала что-то не так, честно говоря, это две концепции, которые обычно плохо сочетаются друг с другом. Люди часто пытаются «подделать» наследование с помощью статических методов и т. д., и это обычно плохо заканчивается — это звучит как вариация на эту тему.

Если вы сможете описать свою более широкую картину, мы сможем помочь вам больше. Между прочим, я призываю вас избегать статики вообще ради тестируемости. Они подходят для настоящих констант, но если это что-то вроде конфигурации, лучше передать соответствующие настройки при создании объекта (IMO).

РЕДАКТИРОВАТЬ: я вижу четыре варианта, которые лучше моделируют вашу ситуацию:

  1. Используйте аннотации: см. ответ True Soft
  2. Сделайте maxHealth методом, чтобы вы могли спросить любого игрока, каково его максимальное здоровье — тогда это полиморфно, поэтому его можно переопределить в каждом классе.
  3. Модель Player и PlayerClass отдельно:

    public class Player {
        private final PlayerClass playerClass;
        private int health; // etc
    }
    
    public class PlayerClass {
        private final int maxHealth; //etc
    }
    

    Таким образом, вы можете иметь наследование на уровне "класса игрока", но вам это не обязательно - вы можете создать несколько PlayerClass экземпляров, которые ведут себя одинаково, но имеют разные характеристики... или вы можете создать подкласс PlayerClass, чтобы задать собственное поведение. В этот момент вам могут вообще не понадобиться разные подклассы Player.

  4. То же, что и идея 3, но с использованием перечисления:

    public enum PlayerClass {
        ELF(10), DWARF(9), HUMAN(5);
    
        private final int maxHealth;
        private PlayerClass(int maxHealth) {
            this.maxHealth = maxHealth;
        }
    }
    

Лично я предпочел бы окончательный вариант, я подозреваю. Вы можете по-прежнему переопределять поведение, но у вас есть фиксированный набор возможных классов, который, вероятно, достаточно точно моделирует вашу игру.

person Jon Skeet    schedule 21.10.2011
comment
› Нет – как бы вы ожидали, что это будет работать, если бы два подкласса пытались сделать одно и то же? Если › у вас есть статические конечные поля, они должны быть инициализированы классом, который их объявляет. Аааа конечно. В основном то, что я пытаюсь сделать, это внедрить систему классов в игру, над которой я работаю. У каждого игрока может быть класс, и каждый класс должен иметь разные атрибуты. (Скорость, здоровье и т.д.) - person lowq; 21.10.2011
comment
Но я не чувствую, что каждый экземпляр класса должен каждый раз выделять maxHealth, maxEnergy и т.д. - person lowq; 21.10.2011
comment
Я иду в данный момент, но отвечу через некоторое время. - person Jon Skeet; 21.10.2011
comment
Теперь я понимаю, что мой первоначальный вопрос был в меру глупым. Они не должны быть статическими для суперкласса, учитывая, что они должны меняться между классами. Я обнаружил, что самый простой способ - сохранить их окончательными, но передать значения через конструктор. (супер()) Извините за это D: - person lowq; 21.10.2011
comment
@user984799: Но если они только доступны для экземпляров, но всегда одинаковы для экземпляров одного и того же класса, может показаться, что вы моделируете немного плохо — см. мой ответ о разделении игрока класс от игрока. - person Jon Skeet; 21.10.2011

Что касается ответа Джона Скита, я не думаю, что это так уж плохо: «Если вы пытаетесь использовать статические поля и наследование вместе». Я предлагаю вам использовать аннотации:

@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();
    }
}
person True Soft    schedule 21.10.2011
comment
Итак, вы предложили что-то, что не является статическими полями... это хорошо, но каким образом это противоречит моей рекомендации не использовать статические поля? - person Jon Skeet; 21.10.2011
comment
Оно не является статическим, но ведет себя как статическое поле (значение относится к классу, а не к экземпляру). - person True Soft; 21.10.2011
comment
Я бы не стал рассматривать это как попытку использовать статические поля и наследование вместе - уж точно не так, как это было в OP. Честно говоря, я все еще думаю, что лучше отделить данные игрока от класса данных игрока. Нет необходимости в размышлениях, нет шансов, что подкласс не объявит аннотацию и т. д. - person Jon Skeet; 21.10.2011
comment
В то время, когда я отвечал на этот вопрос, ОП еще не сообщил подробности того, что он пытался сделать. Может быть, мое решение не самое лучшее в его случае, но в остальных случаях я считаю его идеальным. - person True Soft; 21.10.2011