Наследование конечных полей в Java? - PullRequest
10 голосов
/ 10 января 2012

Что происходит, когда суперкласс имеет поле, помеченное как окончательное, но подкласс переопределяет (скрывает?) Это поле? «Финал» не останавливает это, не так ли? Конкретный пример, над которым я работаю, - это класс Building, от которого наследуются различные типы зданий. Стоимость каждого типа, помимо прочего, должна быть окончательной для каждого подкласса, но каждый тип здания должен иметь свою стоимость.

Редактировать: С тех пор я понял, что понятия не имел, о чем говорил выше. Что я действительно хочу, так это статические переменные стоимости. Однако, если я объявляю эти статические переменные в суперклассе, они являются статическими для суперкласса, поэтому Subclass1.cost, например, ссылается на то же значение, что и Superclass.cost или Subclass2.cost. Как я могу сделать переменные, которые являются статическими для каждого подкласса, без необходимости объявлять их в каждом классе.

Ответы [ 3 ]

16 голосов
/ 10 января 2012

Ключевое слово final применительно к полям класса Java не имеет ничего общего с наследованием. Вместо этого это указывает, что за пределами конструктора это поле не может быть переназначено.

Java обрабатывает скрытие и переопределение имен по отдельности. Переопределение фактически изменяет наблюдаемое поведение программы во время выполнения, переключая, какая функция вызывается, в то время как скрытие имени изменяет программу, изменяя статическую интерпретацию того, какое поле является ссылкой. final применительно к переопределению работает только для методов, потому что поля в Java не могут быть переопределены. Использование final в этих различных контекстах, к сожалению, немного сбивает с толку, и нет способа предотвратить скрытие имени поля в подклассе.

Если вы хотите, чтобы здания имели разные затраты, одним из вариантов будет иметь переопределенный метод getCost, который переопределяется по-разному в каждом производном классе. В качестве альтернативы, вы можете иметь одно поле protected или private в базовом классе, в котором хранится стоимость, а затем каждый подкласс может установить это поле либо напрямую (если это protected), либо через конструктор базового класса (если это поле private).

Надеюсь, это поможет!

4 голосов
/ 10 января 2012

Вы можете сделать это двумя способами: создать функцию доступа и скрыть само поле или передать стоимость сборки конструктору суперкласса из подкласса.Вы можете объединить их и создать свойство, которое не может быть переопределено подклассами:

public class Building {
    private final int cost;

    protected Building(int cost, ...) {
        this.cost = cost;
    }

    public final int getCost() {
        return cost;
    }
}

public class Cottage extends Building {
    public Cottage() {
        super(COTTAGE_COST, ...);
    }
}
2 голосов
/ 10 января 2012

Согласен с другими ответами, но я думаю, что следующая реализация лучше в этом случае:

    public abstract class Building {

        private final int cost;

        public Building(int cost) {
            this.cost = cost;
        }

        public final int getCost() {
            return cost;
        }
    }

    class Skyscraper extends Building {
        public Skyscraper() {
            super(100500);
        }
    }

Конечно, поле может быть обнародовано, но это другая история ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...