Kotlin: преобразовать переменные в ненулевые, если условие истинно - PullRequest
0 голосов
/ 05 января 2019

Я имею в виду следующее.

Рассмотрим этот код:

// Can be a Long or null
val data1= param1.toLongOrNull()
val data2= param2.toLongOrNull()
val dataN= paramN.toLongOrNull()

// Proceed with the action if ALL of the data are not nulls
if(notNull(data1, data2, dataN)){
    // do something with data1,2,N
}

notNull() - это служебная функция, которая принимает список переменных аргументов. Возвращает true, если все аргументы не равны нулю.

fun <T> notNull(vararg elements: T): Boolean {
    elements.forEach {
        if (it == null) {
            return false
        }
    }
    return true
}

У меня проблема в том, что Котлин не знает, что внутри блока if данные1,2, N не могут быть нулевыми. В результате этого не удается скомпилировать:

if(notNull(data1, data2, dataN)){
     data1 + data2 + dataN
     // Fail: Required Long, Found Long?
     // Operator + not allowed on nullable receiver.
}

С другой стороны, если переменные явно проверяются на нуль, то Котлин знает, что это нормально, и не жалуется.

if(data1!=null && data2!=null && dataN!=null){
     data1 + data2 + dataN
}

Было бы неплохо "настроить" метод notNull таким образом, чтобы Котлин знал, что, как только он возвращает значение true, любой из переданных параметров не может быть нулевым внутри блока.
Это возможно?

1 Ответ

0 голосов
/ 05 января 2019

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

inline fun <T> doIfNotNull(elements: Array<T?>, block : (Array<T>) -> Unit) {
    val validElements = arrayListOf<T>()
    for (i in elements) {
       if (i == null) return
       validElements.add(i)
    }
    block.invoke(validElements.toArray(elements))
}

Использование с varargs (должен быть последним параметром, сделать функцию приемника первым аргументом, что не очень приятно);

inline fun <T> doIfNotNull(block : (Array<T>) -> Unit, vararg elements : T?) {
    val validElements = arrayListOf<T>()
    for (i in elements) {
       if (i == null) return
       validElements.add(i)
    }
    block.invoke(validElements.toArray(elements))
}

Пример:

fun test() {
    val elements = arrayOf(1L, 2L, null)
    doIfNotNull(elements, {
        it.sum()
    })
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...