Наследование полей в Java?

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

Edit: с тех пор я понял, что понятия не имел, о чем я говорил выше. Что я на самом деле нужны статические переменные затраты. Однако, если я объявляю эти статические переменные в суперклассе, они статичны для суперкласса, поэтому Подкласс1.стоимость, например, относится к тому же значению, что и суперкласс.стоимость или Подкласс2.стоимость. Как я могу сделать переменные статическими для каждого подкласса, не объявляя их в каждом классе.

3 ответов


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

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

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

надеюсь, что это помогает!


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

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, ...);
    }
}

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

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

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