Финальное наследование полей в Java - PullRequest
1 голос
/ 21 октября 2011

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

Ответы [ 2 ]

5 голосов
/ 21 октября 2011

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

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

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

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

  1. Использовать аннотации: см. Ответ True Soft
  2. Создайте maxHealth a метод , чтобы вы могли спросить любого игрока, каково его максимальное здоровье - это тогда полиморфно, поэтому может быть переопределено в каждом классе
  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;
        }
    }
    

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

1 голос
/ 21 октября 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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...