https://kotlinlang.org logo
Title
m

m

12/04/2017, 7:11 AM
не ArrayList?
g

gildor

12/04/2017, 7:12 AM
ArrayList это просто одна из имплементаций. Со стороны JVM нет разницы между List и MutableList, все в итоге в байткоде будет java.util.List
m

m

12/04/2017, 7:12 AM
жаль.. спасибо за ответ
g

gildor

12/04/2017, 7:14 AM
Почему жаль? Интерфейс листа в джаве всегда имеет мутабельные методы. И как я понимаю runtime эксепшн должен быть, даже после каста к MutableList, так как ImmutableList кидает UnsupportedOperationException если вызвать add/remove/etc, просто если использовать котлиновский интерфейс List, то там этих методов не будет при этом ImmutableList не позволит поменять контент листа даже если его передать в Java или явно кастонуть к MutableList
m

m

12/04/2017, 7:26 AM
Жаль что компиляция возможна. Runtime ошибка меня не устраивает
g

gildor

12/04/2017, 7:27 AM
В Java тоже runtime ошибка
Kotlin хотя бы позволяет спрятать методы, которые эту рантайм ошибку вызывают через интерфейс kotlin.collections.List который не имеет методов изменяющих контент
m

m

12/04/2017, 7:29 AM
Да , но в java можно сконфигурировать lint падать если используются deprecated methods как ImmutableList.add
Плюс в java не возможно кастить его в ArrayList
g

gildor

12/04/2017, 7:30 AM
но ведь lint не спасает от ошибок если передать immutable в метод который принимает просто java.util.List, довольно легко потерять тип (и это распространненая практика, возвращать наиболее абстрактный класс) и использовать ImmutableList как обычный List, причем случайно
Ну и в Kotlin его невозможно кастить в ArrayList
А в Java можно даже не кастить
m

m

12/04/2017, 7:33 AM
Так в Java просто можно в подконтрольном коде не декларировать метод с List параметрами а декларировать как ImmutableList
g

gildor

12/04/2017, 7:34 AM
В Kotlin в кодконтрольном коде можно использовать kotlin.collections.List
Впрочем как и ImmutableList
m

m

12/04/2017, 7:35 AM
Ну так в Коtlin же возможна успешная конвертация его в ModifableList
👎 1
g

gildor

12/04/2017, 7:35 AM
Но ведь и в Java возможен его каст в List, это совершенно таже ситуация
MutableList это тоже самое что интерфейс List в Java
я просто не вижу никакой разницы с Java, разве что да, статические анализаторы могут отловить определенный процент подобным ошибок, вроде явного вызова метода, бросающего exception
Кстати это можно сделать и в Kotlin без проблем, достаточно включить Warnings as Error http://kotlinlang.org/docs/reference/whatsnew12.html#warnings-as-errors
точно так же Kotlin будет ругаться на использование Deprecated метода и падать при билде в случае включения данной опции
m

m

12/04/2017, 7:41 AM
Так в Java ето работает и так
g

gildor

12/04/2017, 7:43 AM
А в Java это разве можно сделать?
нет, я не думаю что такой способ есть и не вижу как это можно реализовать, потому что сам по себе интерфейс java.util.List имеет методы add/remove
m

m

12/04/2017, 7:44 AM
Ну вот. Жаль
g

gildor

12/04/2017, 7:44 AM
т.е. есть огромное число совершенно валидных ситуаций, когда тип приводится к List и все, тут никакие провверки не помогут
Единственное радикальное решение, которое исправляет исторчник проблемы (java.util.List) это полностью отказаться от стандартных Java листов и сделать свою имплементацию и иерархию интерфейсов, но придется везде конвертировать из листа и в лист, что бы использовать с существующим кодом
мне кажется ситуация, когда кто-то закастил kotlin.collections.List к MutableList и получил при использовании add за это в ответ UnsupportedOperationException совершенно валидной, можно и несовместимые типы закастить и получить ClassCastException
m

m

12/04/2017, 7:49 AM
Да. Ето понятно. Но мне нравится guava)
g

gildor

12/04/2017, 7:51 AM
У гуавы ведь та же самая проблема, они имплементят java.util.List
Ну т.е. не проблема гуавы конечно)
m

m

12/04/2017, 7:51 AM
Да, но я в подконтрольном коде использую только колекции guava
g

gildor

12/04/2017, 7:54 AM
все же мне кажется kotlin.collection.List более чистым решением, по крайней мере для своего Kotlin кода, по крайней мере методы просто не доступны, а не deprecated
Но в случае смешаной кодовой базы с Java наверное ImmutableList все же более безопасное решение
Кстати есть еще такой прототип от JB: https://github.com/Kotlin/kotlinx.collections.immutable
m

m

12/04/2017, 9:04 AM
Спасибо.. А известно когда релиз?
g

gildor

12/04/2017, 9:07 AM
Не знаю, думаю можно спросить @ilya.gorbunov так как он автор KEEP - https://github.com/Kotlin/KEEP/blob/master/proposals/stdlib/abstract-collections.md
i

ilya.gorbunov

12/06/2017, 5:38 PM
Про релиз могу подсказать, что пока еще не скоро, т.к. есть нерешенные проблемы в API и нет достаточно хорошей имплементации.
Напомните, какие проблемы вы хотите решить использованием ImmutableList?
m

m

12/06/2017, 6:35 PM
Ммм.. Хочу иметь гарантию что содержимое экземпляра класса ImmutableList невозможно будет удалять/добавлять/заменять никаким образом (рефлексия не в счет). То есть, например, ни после safe cast в MuttableList, ни после unsafe cast в MuttableList (как это сейчас с guava).
i

ilya.gorbunov

12/06/2017, 6:37 PM
Возможно тогда хватит обертки над списком, сделанной с помощью
java.util.Collections.unmodifiableList
m

m

12/06/2017, 6:44 PM
а, тогда дополнительное условие: хочу чтоб либо (1) в классе ImmutableList методьі add, delete и т.д. бьіли deprecated (как в guava) чтобьі можно бьіло сконфигурировать lint падать если он заметит использование deprecated методов, либо (2) в классе ImmutableList методьі add, delete и т.д. отсуствовали. Вариант 2 предочтительнее
А, и это хотелки на все Immutable колекции, не только ImmutableList.
.. То есть эти Immutable колекции не должно бьіть возможньім кастить к Muttable колекции..
g

gildor

12/07/2017, 1:01 AM
Если вы уже используете ImmutableList из Guava то Collections.unmodifiableList уже точно не нужен
в классе ImmutableList методьі add, delete и т.д. бьіли deprecated
Для этого придется использовать этот класс напрямую везде в коде вместо интерфейса. И все равно есть множество случаев где тип потеряется при передаче в метод к примеру.
ImmutableList методьі add, delete и т.д. отсуствовали
Их там просто не будет на стороне Kotlin, точно так же как и сейчас, т.к. интерфейс kotlin.collection.List не имеет методов модификациию И они точно будут на стороне Java. И эту проблему не решить без своей кастомной иерархии интерфейсов коллекций
сконфигурировать lint падать если он заметит использование deprecated методов
Это уже возможно с помощью флагов Kotlin компилятора
не должно бьіть возможньім кастить к Muttable колекции
Запретить кастить вы не можете, вы и сейчас что в Java, что в Kotlin можете написать
"" as Int
, тут только падать на ворнингах поможет и то не всегда. И вообще запретить кастить даже без ворнинга не получится, просто по причине того, что Mutable интерфейс наверняка будет наследников Immutable интерфейса (как это сейчас и работает в Kotlin) иначе очень его не удобно использовать. И kotlinx.collections.immutable эту проблему вам не решат, так же как она не решается через Guava что на стороне Kotlin, что на стороне Java. Но если честно я не вижу большой проблемы совсем, если кто-то пишет код который кастит без проверки типа и затем пытается поменять внутреннее состояние объекта то это его проблема, такой код плох сам по себе. kotlin.collections.List решает большинство случаев со случайной модификацией, но если хочется серьезной защиты от модификации, то просто можно обернуть в Collections.unmodifiableList или использовать Guava ImmutableList как основу для коллекции и в дальнейшем использовать интерфейс kotlin.collections.List
m

m

12/07/2017, 8:35 AM
Для этого придется использовать этот класс напрямую везде в коде вместо интерфейса.
Да, я так и делаю. Для этого это и нужно.
Если вы уже используете ImmutableList из Guava то Collections.unmodifiableList уже точно не нужен
Дело в том что ImmutableList из Guava в Kotlin возможно кастить в MutableList - это и делает бесполезньім использования ImmutableList из Guava в Kotlin.
g

gildor

12/07/2017, 8:39 AM
Нет, это не так
Вы в java можете тоже кастить ImmutableList в List, но это не дает возможности менять содержимое
Точно так же и котлин, вы можете скастить, но поменять содержимое не получится
ImmutableList защищает лист от модификации, не важно к какому из родительских интерфейсов он прикасчен
m

m

12/07/2017, 8:41 AM
да но в java я не могу кастить
List o1 = (ArrayList) ImmutableList.of();
- не позволит компилятор
g

gildor

12/07/2017, 8:41 AM
Ну так вы и в Котлине не можете это сделать
m

m

12/07/2017, 8:42 AM
с guava ImmutableList могу
g

gildor

12/07/2017, 8:42 AM
Зато в Java можете
List o1 = ImmutableList.of();
Нет, если вы попытаетесь прикастить к ArrayList, то получите ClassCastException
m

m

12/07/2017, 8:44 AM
Я имел ввиду что в Kotlin я могу c guava ImmutableList сделать так
val mutableIList = ImmutableList.of(1,2) as MutableList<Int>
Так вот, я и хочу чтобьі в Kotlin бьіли Immutable колекции которьіе в частности нельзя кастить в Mutable колекции
g

gildor

12/07/2017, 8:47 AM
Вы можете скастить, но это не даст клиенты модифицировать лист
mutableIList.add(3) //UnsopportedOperationException
m

m

12/07/2017, 8:48 AM
Mutable интерфейс наверняка будет наследников Immutable интерфейса (как это сейчас и работает в Kotlin) иначе очень его не удобно использовать.
жаль(
g

gildor

12/07/2017, 8:48 AM
Вы только что написали 100% аналог Java кода: mutableIList = (List) ImmutableList.of(1,2)
m

m

12/07/2017, 8:49 AM
Да, но мьі же хотим сделать Kotlin лучше java
g

gildor

12/07/2017, 8:50 AM
Просто вы пишете, что Java каким то образом защищает вас от такого поведения, я же говорю что нет, поведение идентичное
жаль(
Вы всегда можете сделать свою иерархию классов с полностью кастомными интерфейсами которые делегируют имплементацию в ту же Guava и попробовать с ней поработать, это просто очень неудобно иметь 2 несовместимых интерфейса коллекций (нельзя просто взять и передать мутабельную коллекцию в метод который требует иммутабельный) которые постоянно приходится конвертировать еще и в платформенный java.util.List
m

m

12/07/2017, 8:52 AM
В Java просто уже существует много всяких статических анализаторов которьіе можно настроить падать при компиляции
g

gildor

12/07/2017, 8:52 AM
Какой статический анализатор будет ругаться на это?
mutableIList = (List) ImmutableList.of(1,2)
или на это:
void mutateList(List list) { … }

mutateList(ImmutableList.of(1,2))
m

m

12/07/2017, 8:53 AM
error-prone (хотя не уверен)
g

gildor

12/07/2017, 8:53 AM
Я совсем не уверен, так как абсолютно валидный кейс
особенно если mutableIList еще глубже передается
m

m

12/07/2017, 8:56 AM
Хорошо, возможно в Java и нет таких анализаторв..
g

gildor

12/07/2017, 8:57 AM
Конечно, хочется сделать Котлин лучше, но всегда есть ограничения просто логические и практического плана, если был бы какой то способ это решить то его можно было применить
m

m

12/07/2017, 8:58 AM
Но будущая возможость в Kotlin кастить в Immutable в Mutable это как-то странно наверное..
g

gildor

12/07/2017, 8:58 AM
но лечение (полностью несовместимые интерфейсы мутабильных и иммутабельных коллекций, не совместимые с java.util.List) хуже болезни (программист может явно прикастить к мутабельному типы, вызвать метод add/remove и получить UnsupportedOperationException)
m

m

12/07/2017, 8:59 AM
это да..
g

gildor

12/07/2017, 8:59 AM
Это не возможность Kotlin, это то, как работают интерфейсы на JVM и много где еще
m

m

12/07/2017, 8:59 AM
хорошо, понятно
но может бьіть тогда хотя бьі компилятор Kotlin будет предупреждать о кастинге в Immutable в Mutable ?
g

gildor

12/07/2017, 9:08 AM
Он и будет предупреждать на стороне Котлин о том что “This cast can never succeed” и падать с ClassCastException
но! Если вы его прикастите к List, который на стороне Java превратится в java.lang.List
т.е. на стороне Kotlin все работает, но при использовании на стороне Java нет
m

m

12/07/2017, 9:11 AM
Эх..
g

gildor

12/07/2017, 9:12 AM
и кстати тут вы правы, ImmutableList из kotlinx.immutable.collections спасет от проблемы с кастом, но опять же, только на стороне Kotlin: https://try.kotlinlang.org/#/UserProjects/esb1haphvlhi3d0jasdbj5adh9/n6lb53kucglob8ofpnu4s7rie7