@kotlin_lang

Страница 64 из 982
Boris
03.03.2017
12:56:10
этот код должен быть где-то вызван

так вот если метод вызывать до вызвова кода, который инежектит, то никакого объекта там не будет

Roman
03.03.2017
12:59:54
это понятно. но как при наследовании это обойти?

Boris
03.03.2017
13:00:57
часто самый простой способ обойти проблемы наследования это наследование не использовать

Google
Roman
03.03.2017
13:01:25
ну в данном случае не думаю что это хороший путь

мне вот что непонятно. почему не могло быть сделано так, что сначала устанавливаются фактические значения свойств из параметров конструктора и только потом вызывается конструктор базового класса?

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

Стас
03.03.2017
13:05:21
а что с lazy init для пропертей? не о том?

Roman
03.03.2017
13:06:02
Это вообще очень странно и неправильно. kotl.in/issue
что именно странно и неправильно? мое рассуждение или текущая реализация?

Boris
03.03.2017
13:06:08
нет, вызывать конструктор до базового никак не возможно

Roman
03.03.2017
13:06:27
Quantum Harmonizer
03.03.2017
13:07:13
что именно странно и неправильно? мое рассуждение или текущая реализация?
Текущая реализация неадекватна. Наследник может полагаться на инициализированные поля суперкласса, это было бы нормально.

Roman
03.03.2017
13:08:22
Текущая реализация неадекватна. Наследник может полагаться на инициализированные поля суперкласса, это было бы нормально.
в данном случае не инициализированы поля дочернего класса в момент работы конструктора родительского. просто потому что сначала работает родительский конструктор, потом дочерний, а поля выставляются там

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

Google
Roman
03.03.2017
13:10:06
чисто технически - ни с чего. но вот если он этого не делает, то код из родительского конструктора легко ломает все с NPE

стоит только из конструктора обратиться к методу дочернего класса, который использует поле-параметр

и это совсем не очевидно

очевидно что оно так будет работать, но не очевидно когда пишется наследник

Quantum Harmonizer
03.03.2017
13:11:40
чисто технически - ни с чего. но вот если он этого не делает, то код из родительского конструктора легко ломает все с NPE
Почему родительский конструктор ломается? Он зависит от наследника? Вызывает не-финальный метод?

Roman
03.03.2017
13:11:49
в джаве так выстрелить себе в ногу нельзя - все поля класса железно инициализированы к моменту работы любого метода

ну или метод через рефлексию или через кодогенерацию, что не суть

Quantum Harmonizer
03.03.2017
13:12:44
да, он вызывает не финальный метод
Так же можно выстрелить и в Java, я думаю. Вызывать нефинальные методы в конструкторе как раз из-за этого и не рекомендуется.

Roman
03.03.2017
13:12:54
хм

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

и да это похоже, но в котлине как-то имхо менее очевидно за красотой и простотой проперти-пераметров

даже, если исходить из того, что в джаве тоже самое. почему нельзя в котлин классе сделать иначе? ведь требование в Java чтобы вызов базового конструктора шел первым связано имхо как раз с тем, что в дочернем конструкторе может быть произвольная логика, которая может обращаться к полям базового класса. но в данном случае мы точно знаем что наши параметры-поля - новые и что код их инициализации ничего тронуть не может в принципе

Quantum Harmonizer
03.03.2017
13:16:56
и что будет?
Here’s a subclass that overrides the overrideMe, method which is erroneouslyinvoked by Super’s sole constructor: public final class Sub extends Super { private final Date date; // Blank final, set by constructor Sub() { date = new Date(); } // Overriding method invoked by superclass constructor @Override public void overrideMe() { System.out.println(date); } public static void main(String[] args) { Sub sub = new Sub(); sub.overrideMe(); } }You might expect this program to print out the date twice, but it prints out null the first time, because the overrideMe method is invoked by the Super constructor before the Sub constructor has a chance to initialize the date field.

Dmitry
03.03.2017
13:17:36
Так же можно выстрелить и в Java, я думаю. Вызывать нефинальные методы в конструкторе как раз из-за этого и не рекомендуется.
Таки да, вызов non-final методов из конструктора крайне не рекомендуется и дело тут не в Котлине (собственно это хороший способ выстрелить себе в ногу) Пример: http://www.informit.com/articles/article.aspx?p=20521

Roman
03.03.2017
13:18:03
но код инициализации полей-параметров ведь МОЖЕТ быть вызван технически до кода из базового конструктора, разве нет?

то есть либо это недоработка компилятора, либо какое-то техническое ограничение, которое я просто пока не понимаю

Quantum Harmonizer
03.03.2017
13:20:10
Google
Roman
03.03.2017
13:20:39
Код инициализации — это такой же код конструктора, как и код в init.
с тем исключением, что компилятор может гарантировать его необращение к данным базового класса

значит конкретно этот код может и должен имхо быть размещен ДО вызова базового конструктора

тогда такой выстрел в ногу будет невозможен

Dmitry
03.03.2017
13:24:01
Насколько помню до завершения вызова конструктора формально объект еще не сформирован, потому даже для final поля можно увидеть непроинициализированное значение (все это из-за вызова методов из конструктора)

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

Quantum Harmonizer
03.03.2017
13:25:38
с тем исключением, что компилятор может гарантировать его необращение к данным базового класса
Как раз наоборот, можно обращаться к данным базового класса. open class Base { val size = 10 } class Big : Base { val actualSize = 5*size }

Roman
03.03.2017
13:26:28
или хочешь сказать что это будет неконсистентно если свойства будут инициализироваться в разных местах?

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

Quantum Harmonizer
03.03.2017
13:28:37
мы же говорим про параметры-свойства а не про любые свойства
Инициализация чего бы то ни было — это действия, которые должны выполняться сначала у родителя, затем у потомка.

Quantum Harmonizer
03.03.2017
13:29:31
на чем основано это утверждение?
На поведении Java, и, за нею, Kotlin.

Roman
03.03.2017
13:31:55
На поведении Java, и, за нею, Kotlin.
но в джаве нет параметров-свойств - там в принципе нет такой семантики. код в конструкторе в джаве - по определению произвольный и написан программистом, никакой своей магии компилятор не добавляет

Quantum Harmonizer
03.03.2017
13:32:55
/* можно переопределить get() так, чтобы он не зависил от инициализированности :) */

Roman
03.03.2017
13:34:17
потому что свойства это парметры смешанные с неким кодом их установки в поля класса. а значит есть некий код, который дописывает за тебя компилятор и значит к нему не применимо это требование (если он не использует данные базового класса)

Roman
03.03.2017
13:37:05
ну да, но это новая штука которой не было в джаве

Boris
03.03.2017
13:37:15
Про что вообще спор?

Google
Boris
03.03.2017
13:37:29
Есть данность изменить которую не в наших силах

Quantum Harmonizer
03.03.2017
13:37:43
вот эту фразу не понял, поясни плз
class Sub : Super { val i = 100500 // из конструктора суперкласса видно 0 override fun getNumber() = i }class Sub : Super { val i: Int get() = 100500 // из конструктора суперкласса видно 100500 (ну, я так думаю) override fun getNumber() = i }

Roman
03.03.2017
13:38:29
Boris
03.03.2017
13:38:30
Да и смысла нет. Реализация наследования вполне норм. Этот механизм вообще сложный, потому и кучку подводных камней имеет

Dmitry
03.03.2017
13:38:32
Спор почему JMM работает именно так, а не как удобно мне

Boris
03.03.2017
13:39:07
почему? вдруг в 1.2 сделают? =)
Конечно не сделают. То как есть это лучшее из того на что можно рассчитывать

Igor
03.03.2017
13:39:14
почему? вдруг в 1.2 сделают? =)
Кстати, а что нам ждать в 1.2?

Roman
03.03.2017
13:39:22
Сказали же уже выше, что это не так
я уже и согласился выше =)

Admin
ERROR: S client not available

Boris
03.03.2017
13:39:40
Руслан
03.03.2017
13:39:47
Это в 1.1.1

Roman
03.03.2017
13:39:51
Конечно не сделают. То как есть это лучшее из того на что можно рассчитывать
мне интересно почему. не спора ради, а реально понять с чем связано такое ограничение.

Руслан
03.03.2017
13:40:07
Kotlin Native - 1.2?

Boris
03.03.2017
13:40:18
Это не ограничение

Igor
03.03.2017
13:40:28
Тут вот нам 15 марта обещают расскзать про kotlin 2.0

Boris
03.03.2017
13:40:29
Это то как работает наследование

Dmitry
03.03.2017
13:40:30
Кстати, а что нам ждать в 1.2?
не экспериментальные корутины?)

Igor
03.03.2017
13:41:25
не экспериментальные корутины?)
Это не интересно (эксперементальных хватает) А вот алиасы на пакеты (как в scala) - этого не хватает.

Google
Андрей
03.03.2017
13:42:28
Легко, можно его вообще не вызывать.
Нельзя. Так как в Джава если не вызвать либо super(), либо this() явно, то компилятор самым первым вызовом неявно подставит super()

Igor
03.03.2017
13:42:46
А для каких кейзов это надо?
Перед скалистами понтаваться ? конечно

И еще тайп классы можно (вон в C# тоже об этом думаю)

Boris
03.03.2017
13:43:30
Нельзя. Так как в Джава если не вызвать либо super(), либо this() явно, то компилятор самым первым вызовом неявно подставит super()
Конечно не вызвать конструктор родителя нельзя. На этом вообще строится вся консистентность наследования

Quantum Harmonizer
03.03.2017
13:43:34
Roman
03.03.2017
13:44:20
речь не о концепции наследования для программиста и не об ограничениях/правилах которые накладывает компилятор на него. речь о реализации компилятора

Boris
03.03.2017
13:45:17
Это не байткоду противоречит, а смыслу наследования

Roman
03.03.2017
13:46:51
Это не байткоду противоречит, а смыслу наследования
ну это как посмотреть. ведь сам дочерний объект в памяти уже создан в момент вызова конструктора базового класса. что мешает и часть полей инициализировать к этому моменту? кстати в джаве дефолтные значения поля дочернего класса получают до вызова конструтора базового класса. что тоже можно расценивать как аналогичное нарушение наследования

Roman
03.03.2017
13:48:24
Раз уж зашли на такой уровень, создание объекты и вызов конструктора — две разных инструкции :)
ну так и я о том же. ничего не мешает между ними еще какие-то инструкции засунуть =))

Boris
03.03.2017
13:55:40
наследование и без того механизм очень сложный, чтобы с ним хоть как-то иметь возможность иметь дело нужны очень строгие правила работы этого механизма. Опять же когда проектируешь базовый класс, ты хоть в чем-то должен быть уверен -- например в целостности данных базового класса, поэтому есть недвусмысленная последовательность инициализации класса и его предков

а засунут-то конечно можно куда угодно что угодно

хоть пиши компилятор, который убивает систему при запуске

но насколько я представляю у котлина другие цели

Igor
03.03.2017
14:02:53
? да, ради этого нужно
Ну рили я уже это объяснял, вот тут это поднималось https://discuss.kotlinlang.org/t/imports/1571/4

Roman
03.03.2017
14:09:57
Ну рили я уже это объяснял, вот тут это поднималось https://discuss.kotlinlang.org/t/imports/1571/4
а чем это отличается от того, что уже есть? import bar.Bar as bBar // bBar stands for 'bar.Bar'

Igor
03.03.2017
14:13:28
Тем что нужно руками прописывать каждую зависимость (плюс скоуп функций плохо понимается без доп. квалификатора).

Руслан
03.03.2017
18:30:07
https://github.com/icela/FriceEngine-DSL#simplest

Закинули в котлин линк)

1. Взяли стиль лого JB 2. код на китайском

Страница 64 из 982