Вспомним наследование

  • 7
  • Недоступна
Исправить наследование во всех классах, чтобы вывод метода main был CCBAYS.
Вы не можете решать эту задачу, т.к. не залогинены.
Комментарии (104)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий вы должны авторизоваться
Вадим QA Automation Engineer в СберТех
13 апреля, 20:44
Кто-нибудь может мне помочь понять, почему super.getClass().getName() возвращает "com.javarush.task.task24.task2411.Solution$1" ? Я так понимаю "Solution$1" это название, которое дал компилятор нашему анонимному классу. Так почему super ссылается на текущий класс?
Anonymous #2489173
28 уровень
7 апреля, 13:11
Не особо понимаю функциональность правильного решения. Класс в одном файле реализует интерфейс, внутренний класс которого наследуется от того первого класса. Можно практический пример какой-то такой ситуации?
endurance2296
28 уровень, Киев
20 марта, 19:18
Вместо Solution, от C можно унаследовать A, и вывод получается такой же. Но естественно валидатор не пропустил по понятным причинам)
Валерий Федотовских
40 уровень, Москва
18 марта, 14:42
Сделал по инструкции из описания и ничего не понял в начале. Но зато кайфанул, когда постаивл брейкпоинт на строчке
new Solution();
и прогнал всю программу в дебагере через F7. Спойлер: конструктор Solution в реальности выполнится последним!🤣
Даниил Александрович
30 уровень, Тамбов
5 марта, 10:52
решается по требованиям. step by step вникать не стал...
Андрей Овчаренко
28 уровень, Москва
25 февраля, 20:11
Задача решается брутфорсом, в ней не много комбинаций
mishok Support
26 февраля, 09:56
Очередная задача учит читать требования.
Андрей Овчаренко
28 уровень, Москва
26 февраля, 18:50
в требованиях ответ написан, с 10 уровня их можно читать только после решения задачи
Pig Man Главная свинья в Свинарнике
5 декабря 2020, 20:28
Читаю комментарии и вижу, что ни у кого не возникло такого же вопроса, как у меня. Либо для остальных это элементарно, либо они просто не обратили внимание. Но для тех, кто не понял не всю эту тему с порядком создания классов и суперклассов (как по мне, это было не трудно), а вот это: 1. ЗАЧЕМ ТУТ ВООБЩЕ НУЖНО ПИСАТЬ В КОНСТРУКТОРЕ КЛАССА С "B localB = B;" 2. Почему это не вечный цикл? Ответ: 1. Поле интерфейса инициализируется при первом обращении к нему (вернее, это один из тригеров, который может привести к его инициализации). То есть, без этой строчки поле B b останется пустым, а значит, не будет создан объект класса B и не будет нужного вывода в консоль 2. Все поля интерфейсов являются по умолчанию public static final (это даже подписали зачем-то, хотя не нужно. Но видимо, чтобы не забыли). Почему мы не получаем вечный цикл с родителем С: "создать объект класса С, создать объект класса B, но сначала создать объект класса С, создать объект класса B, но сначала С, В, С, В.."? Все элементарно, это поле - static final, оно может быть инициализировано только один раз и является общим для всего интерфейса, а значит, второй раз при создании объекта класса С, объект класса В создан не будет, а просто возьмется из поля B b
Eleonora
34 уровень, Москва
21 января, 16:31
уххх, спасибо тебе, дебажил эту штуку, но что-то туговато доходило))
Михаил
26 уровень, Саратов
24 марта, 15:22
По второму пункту. Выходит что ссылка на объект B присваивается до окончания конструктора. Т.е. в JustAnInterface B B уже имеет ссылку на объект, хотя его конструктор еще не завершился, еще не отработал System.out.print("B").
Sergei
28 уровень, Москва
20 ноября 2020, 08:39
Это что получается объект наследника внутреннего класса создается в конструкторе внешнего класса, раз последней выводится буква "S"? Чет нигде теории я не нашел по таким родственным связям!
Pig Man Главная свинья в Свинарнике
6 декабря 2020, 10:51
Чего? "S" выводится из конструктора Solution:
public Solution() {
    System.out.print("S");
}
В main прямо написано new Solution();, ты о чем вообще? А если ты про все остальные выведенные буквы и почему они вывелись перед S, то вспомни про порядок инициализации полей класса и когда именно вызывается конструктор (он вызывается в самом конце)
Sergei
28 уровень, Москва
7 декабря 2020, 10:25
Про порядок мне известно. Вопрос был в другом. До вызова конструктора класса-наследника (где "S") должен выполняться нестатический блок инциализации того же класса-наследника. А у нас блок иницализации вроде в классе-наследнике, но относится он к анонимному классу. 2 причина по которой мог бы запуститься код в анонимного классе: объект анонимного класса является нестатической переменной того же класса-наследника, но это както не вяжется с тем, что этот объект анонимного класса это краткая форма записи полноценного класса плюс компилируется он в класс а не в поле. Неочевидно мне это все
Pig Man Главная свинья в Свинарнике
7 декабря 2020, 12:05
Ахахахахаха это нужно было еще постараться так запутанно написать. Ладно, я просто напишу ход происходящего: Все, что мы создаем вручную - объект класса Solution, он является наследником класса С, создается родительский объект класса С (в консоли «С»), класс С реализует интерфейс JustAnInterface, и в своем конструкторе инициализирует поле B b объектом класса B (досталось от JustAnInterface), но класс B является наследником класса С, снова создается родительский объект класса С (в консоли «СС»)(почему тут не запускается бесконечный цикл с очередным созданием объекта класса B в конструкторе класса С я написал в комментарии выше). Родительский класс был создан, теперь создаем сам В (в консоли «ССВ»). Отлично, с родительским классов Solution разобрались, теперь инициализируются нестатические поля (я не буду писать каждый раз тут статические, но статических нет, тогда эти, этих нет и т.д. - нафиг надо, слишком запутано будет, их нет и нет). У нас одно поле в Solution A a = new A() {}, оно инициализируется анонимным классом. Анонимный класс создается по принципу создания класса наследника от указанного класса до фигурных скобок - следовательно, у нас в поле А а создается объекта класса ClasseAnonyme extends A (это не настоящее его имя). Поехали: сначала создается родительский объект класса А (в консоли «ССВА»), теперь сам наследник - у анонимного класса конструктора нет, но есть нестатический блок кода, который выведет Y в момент создания класса, если данный анонимный класс является внутренним классом Solution (смотри в интернете касательно образования имен анонимных классов, они состоят из 3 частей) (в консоли «ССВAY»). Ну а теперь мы наконец добрались до конструктора Solution, который выведет S (в консоли «ССВAYS») Все
Pig Man Главная свинья в Свинарнике
7 декабря 2020, 16:48
Понял, нет?
Sergei
28 уровень, Москва
7 декабря 2020, 20:19
Да, спасибо.
У нас одно поле в Solution A a = new A() {}, оно инициализируется анонимным классом
Мой мозг не мог поверить, что так бывает
Pig Man Главная свинья в Свинарнике
7 декабря 2020, 21:14
Так ты наверняка писал такую конструкцию. Что-нибудь наподобие
private List<String> list = new ArrayList<>();
То же самое, ты создаешь в поле объект класса. Только в этом случае объект анонимного класса - вся разница
Sergei
28 уровень, Москва
8 декабря 2020, 05:20
Писал, меня сбил с толку блок инициализации
Mike
35 уровень, Москва
2 января, 22:41
Мне вроде было понятно, что происходит. Но еще раз дополнительно отложилось после Вашего объяснения. Спасибо Вам за такие подробные и качественные объяснения!!!
Pig Man Главная свинья в Свинарнике
3 января, 08:41
👍
Владимир Коземаслов Жук в Муравейнике
19 января, 20:36
Спасибо тебе Pig Man, все по полочкам разложил, работаешь уже ??? P.S. Сложно представить такой код в реальном проекте, когда читал про методологии разработки вроде бы наоборот все стараются максимально упростить, а тут масло масленое.
Pig Man Главная свинья в Свинарнике
20 января, 10:25
Нет, не работаю, учусь. Хотя сейчас у меня тут перерыв в изучении java на пару недель, но скоро вернусь. Дело не в том, что такой же код ты встретишь в реальном проекте, а в том, чтобы ты до конца понял процесс происходящего. Если ты сильно путаешься, то внутренний механизм тебе непонятен, а это плохо, так как может привести к ошибкам уже в реальной работе
Андрей
41 уровень, Иркутск
2 ноября 2020, 12:51
Попытался вникнуть в ход исполнения программы, если где-то мимо - поправьте, плиз: // 1# в методе main создали объект типа Solution(); // 2# так как Solution является наследником класса С, то сначала вызывается конструктор суперкласса С, на экран выводится С // 3# в конструкторе класса С создается объект класса В, который принадлежит интерфейсу JustAnInterface // 4# при создании В сначала вызывается конструктор суперкласса С, на экран выводится С // 4# вызывается конструктор В, на экран выводится В // 5# создается класс А, инициализируются его поля, вызывается конструктор класса А, на экран выводится value - A // 6# создается "а" - объект анонимного класса А(), т.к. это объект анонимного класса, у него нет конструктора, проходит блок инициализации // 7# в этом блоке значение value меняется на "Y", и по условию, если этот класс наследуется от Solution, на экран выводится value = Y // 8# наконец, вызывается конструктор класса Solution, на экран выводится S
Андрей
41 уровень, Иркутск
2 ноября 2020, 13:26
Вот только никак не могу разобраться: получается, что объект нового анонимного класса А является наследником неанонимного класса А, который в свою очередь наследуется от Solution, почему тогда условие if (super.getClass().getName().contains(".Solution$")) выполняется?
Игорь Че Software Developer
2 ноября 2020, 13:32
System.out.println(this.getClass().getName());
System.out.println(super.getClass().getName());
вывод
com.javarush.task.task24.task2411.Solution$1
com.javarush.task.task24.task2411.Solution$1
одинаково