Pull to refresh

Comments 8

В последнем паззлере ошибка: вместо
Function<*>(){}()
должно быть
Function<*>.(){}()
иначе не компилируется.

Ещё в объяснении поправите пожалуйста

antonkeks, в 13 объяснение какое-то совсем неверное. Какой еще компилятор? Какое еще «почему-то»? Какое еще «постарался, но не получилось»? Здесь нет вообще никакой неопределенности и работают исключительно стандартный джавовый механизм загрузки классов.

Котлиновский object — это статический INSTANCE филд в одноименном классе. Инициализация статических филдов происходит в момент инициализации класса, а инициализация классов в джаве отложенная и происходит при первом использовании. Соответственно, в момент первого «println(B.x)» начинает инициализироваться класс B. Ему, для того, чтобы создать этот INSTANCE, нужен класс C. Но в процессе инициализации C при попытке доступа к B.INSTANCE инициализация B не начинается повторно (сама jvm так работает). Соответственно, идет просто чтение еще не инициализированного поля B.INSTANCE (==null) и создание и запись нового объекта в C.INSTANCE. После чего мы выходим из инициализации класса C и спокойно уже обращаемся к его филду (INSTANCE) и создаем красивый, заполненный, B.INSTANCE.

А если заменить Any? на просто Any, то там тоже компилятор ничего дополнительно «пытаться» не начинает. Он просто в конструктор A вставляет проверку на аргумент т.к. он может прийти из джавы и не быть проверенным на стороне вызова. И именно эта проверка и падает. Банальное добавление -Xno-param-assertions в опции компилятора приводит к результату «C null» и с Any тоже.

p.s. По поводу инициализации классов. Вот простой пример, демонстрирующий, что ни бесконечной рекурсии, ни каких-либо ошибок не происходит.
Отлично поломал голову с данными головоломками!

Пожалуйста, объясните что происходит в 15 паззлере? Я спать нормально не могу после него.

Мне потребовалось около получаса чтобы понять, но, кажется, я смог!
Попытаюсь объяснить…

Есть вот такой код:
fun String.someExtension() {}

val string = "some string".someExtension()

println(string)

Тут вроде всё понятно, вызываем экстеншн-функцию, она возвращает kotlin.Unit, печатаем kotlin.Unit

Теперь магия! Берем и объявление someExtension подставляем прямо в место вызова, но название экстеншн-функции после «String.» убираем, она становится анонимной:
val string = "some string".fun String.() {}()

println(string)

Эффект тот же — kotlin.Unit

Теперь осталось String заменить на Function<*> из паззлера и смысл паззлера станет понятен.
Sign up to leave a comment.