class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
}
public void doIt()
{
new Son().printMe();
}
Функция doIt выведет «папа». Есть ли способ заставить его печатать "сын"?
java
inheritance
overriding
Dikla
источник
источник
Ответы:
Да. Но что касается переменной, то она перезаписывается (Давать новое значение переменной. Давать новое определение функции - Переопределить).
Just don't declare the variable but initialize (change) in the constructor or static block.
Значение будет отражено при использовании в блоках родительского класса.
если переменная статическая, то измените значение во время самой инициализации статическим блоком,
или изменить конструктор.
Вы также можете изменить значение позже в любых блоках. Это отразится на суперклассе
источник
class Son extends Dad { static { me = 'son' } }
Короче говоря, нет, нет способа переопределить переменную класса.
Вы не переопределяете переменные класса в Java, вы их скрываете. Переопределение, например, методы. Сокрытие отличается от переопределения.
В приведенном вами примере, объявив переменную класса с именем «me» в классе Son, вы скрываете переменную класса, которую она унаследовала бы от своего суперкласса Dad с тем же именем «me». Скрытие переменной таким образом не влияет на значение переменной класса 'me' в суперклассе Dad.
Для второй части вашего вопроса о том, как заставить его печатать «сын», я бы установил значение через конструктор. Хотя приведенный ниже код довольно сильно отличается от вашего исходного вопроса, я бы написал его примерно так;
JLS дает гораздо больше подробностей о сокрытии в разделе 8.3 - Объявление полей
источник
Person
предполагается заменить в этом примере?Son
иDad
должны наследовать отPerson
, а затем вызватьsuper("Son or Dad");
их конструкторы.Да, просто переопределите
printMe()
метод:источник
printMe()
метода или даже имеет метод, который является статическим?Вы можете создать геттер и затем переопределить его. Это особенно полезно, если переменная, которую вы переопределяете, является подклассом сама по себе. Представьте, что у вашего суперкласса есть
Object
член, но в вашем подклассе он теперь определен какInteger
.источник
Если вы собираетесь переопределить это, я не вижу веской причины сохранять это статичным. Я бы предложил использовать абстракцию (см. Пример кода). :
Теперь мы можем добавить папу:
сын:
и папа встретил милую даму:
Похоже, у нас есть семья, давайте скажем миру их имена:
}
Вывод System.out: Tommy Nancy Dad
System.err такой же, как указано выше (только с красным шрифтом)
Вывод JOption:
Tommy, затем
Nancy, затем
Dad
источник
Это выглядит как недостаток дизайна.
Удалите ключевое слово static и установите переменную, например, в конструкторе. Таким образом, Son просто устанавливает переменную в другое значение в своем конструкторе.
источник
Хотя верно, что переменные класса могут быть скрыты только в подклассах и не могут быть переопределены, все же можно делать то, что вы хотите, без переопределения
printMe ()
в подклассах, и отражение - ваш друг. В коде ниже я опускаю обработку исключений для ясности. Обратите внимание, что объявлениеme
asprotected
не имеет особого смысла в этом контексте, так как оно будет скрыто в подклассах ...источник
... напечатает "сын".
источник
https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html
Это называется скрытие полей
По ссылке выше
источник
только путем переопределения
printMe()
:ссылка
me
наDad.printMe
метод неявно указывает на статическое полеDad.me
, поэтому вы так или иначе изменяете то, чтоprintMe
делает вSon
...источник
Вы не можете переопределить переменные в классе. Вы можете переопределить только методы. Вы должны держать переменные закрытыми, иначе вы можете получить много проблем.
источник
Это действительно печатает «папа», так как поле не переопределено, но скрыто. Есть три подхода, чтобы заставить его печатать «сын»:
Подход 1: переопределить printMe
Подход 2: не скрывайте поле и инициализируйте его в конструкторе
Подход 3: использовать статическое значение для инициализации поля в конструкторе
источник
Переменные не участвуют в отбрасывании. Только методы делают. Вызов метода разрешается во время выполнения, то есть решение о вызове метода принимается во время выполнения, но переменные определяются только во время компиляции. Следовательно, вызывается эта переменная, чья ссылка используется для вызова, а не объекта времени выполнения.
Взгляните на следующий фрагмент:
Когда вы запустите код, консоль покажет:
источник
Конечно, рекомендуется использовать закрытые атрибуты, а также методы получения и установки, но я протестировал следующее, и это работает ... Смотрите комментарий в коде
Оооо ... я просто переопределил правила наследования, или я поставил Oracle в сложную ситуацию? Для меня защищенная статическая строка String Me явно переопределена, как вы можете видеть, когда вы запускаете эту программу. Кроме того, для меня нет никакого смысла, почему атрибуты не должны быть переопределенными.
источник
Почему вы хотите переопределить переменные, когда вы можете легко переназначить их в подклассах.
Я следую этой схеме, чтобы обойти языковой дизайн. Предположим, что в вашей среде есть весомый класс обслуживания, который необходимо использовать в разных вариантах в нескольких производных приложениях. В этом случае лучший способ настроить логику суперкласса - это переназначить его «определяющие» переменные.
источник
Нет. Переменные класса (также применимые к переменным экземпляра) не обладают переопределением в Java, поскольку переменные класса вызываются на основе типа вызывающего объекта. Добавлен еще один класс (Человек) в иерархию, чтобы сделать его более понятным. Итак, теперь у нас есть
Сын расширяет папа расширяет человека
В приведенном ниже коде мы пытаемся перебрать массив объектов Human, Dad и Son, но во всех случаях он печатает значения Human Class, поскольку тип вызывающего объекта был Human.
Будет печатать
Если мы хотим получить доступ к переменной класса фактического объекта из ссылочной переменной его родительского класса, нам нужно явно сообщить об этом компилятору, приведя родительскую ссылку (объект Human) к его типу.
Будет печатать
О том, как часть этого вопроса: - Как уже предлагалось переопределить метод printMe () в классе Son, то при вызове
Переменная класса «папа» папы будет скрыта, потому что ближайшая декларация (из метода Sonme printme ()) «меня» (в классе сына) получит приоритет.
источник
Просто вызовите super.variable в конструкторе подкласса
Выход 10.
источник