2012-01-10 3 views
6

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

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

+0

Сделать поле личное. –

+0

Что-то вроде стоимости меняется время от времени правильно? Зачем делать это окончательно. Я не думаю, что скрывать поле - хорошая идея. –

ответ

11

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

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

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

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

+0

Итак, вы говорите, что сделайте защищенное поле в суперклассе, а затем просто назначили разные значения автоматически в конструкторе подкласса? Звучит разумно. – TheTedinator

+1

@TheTedinator - Это будет работать, если вы откажетесь от модификатора 'final' для поля. Если поле «final», ему нельзя назначить разные значения в конструкторе подкласса. Вместо этого конструктор подкласса должен был бы передать значение до конструктора суперкласса, который должен быть назначен (как я показал в своем ответе). Если суперкласс не присваивает значение в своем конструкторе, код не будет компилироваться; если конструктор подкласса пытается установить значение «конечного» поля из суперкласса, код не будет компилироваться. –

+0

@templatetypedef "это указывает, что вне конструктора это поле не может быть переназначено" на самом деле неверно: окончательное поле не может быть переназначено вообще, даже в конструкторе. Из-за этого конструктор подкласса не может переопределить конечное поле из суперкласса, как заявлял Тед Хопп. – Sebastian

3

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

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

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

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

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