#kotlin
#котлин
Вопрос:
Использование функции минус в списке, не допускающем обнуления, работает правильно…
val listA: Listlt;Stringgt; = listOf("1", "2", "3") val listB : Listlt;Stringgt; = listOf("1", "2", "3") assertEquals(0, listB.minus(listA).size) // Test PASSED
…Но в списке, подлежащем аннулированию, он не работает с оператором безопасного вызова ?. почему?
val listA: Listlt;Stringgt;? = listOf("1", "2", "3") val listB : Listlt;Stringgt;? = listOf("1", "2", "3") assertEquals(0, listB?.minus(listA)?.size) // Test FAILED
Комментарии:
1. Вывод имеет значение времени Int?
Ответ №1:
Это «уловка» Котлина, связанная с тем, как они реализовали дисперсию списков и перегрузили minus
функцию. На самом деле вы вызываете две разные перегрузки minus
функции.
В вашем первом примере вы вызываете перегрузку с помощью этой подписи:
fun lt;Tgt; Iterablelt;Tgt;.minus(elements: Iterablelt;Tgt;): Listlt;Tgt;
Он видит a Listlt;Stringgt;
с параметром an Iterablelt;Stringgt;
( listB
), поэтому T
выводится как a String
, и он может удалить элементы из списка и вернуть пустое Listlt;Stringgt;
значение .
Во втором примере приведенная выше перегрузка не соответствует, поскольку listB?.
означает , что получатель является a Listlt;Stringgt;
, но параметр listA
не является an Iterablelt;Stringgt;
. Это ан Iterablelt;Stringgt;?
. Поэтому вместо этого вызывается другая, менее специфичная перегрузка функции:
fun lt;Tgt; Iterablelt;Tgt;.minus(element: T): Listlt;Tgt;
Поскольку a Listlt;Stringgt;
также является a Listlt;Any?gt;
(из-за ковариации), и a Listlt;Stringgt;?
квалифицируется как an Any?
, функция совпадает с использованием a T
of Any?
. И поскольку сам экземпляр списка не является элементом в listB
возвращаемом списке, в нем не меньше элементов, чем listB
было.
При работе со списками, допускающими обнуление orEmpty()
, эта функция часто пригодится:
val listA: Listlt;Stringgt;? = listOf("1", "2", "3") val listB : Listlt;Stringgt;? = listOf("1", "2", "3") assertEquals("nullable", 0, listB.orEmpty().minus(listA.orEmpty()).size) // PASSES
orEmpty()
является сокращением ?: emptyList()
, и это гарантирует, что вы работаете со списком, не подлежащим аннулированию. Это также удобно для строк, допускающих обнуление.