Как избежать !!в функции, которая возвращает ненулевое значение - PullRequest
0 голосов
/ 05 июня 2018

В приведенном ниже примере функция должна возвращать ненулевые данные.Поскольку данные могут быть изменены в процессе, они должны быть переменными и могут начинаться только с нуля.

Я не могу использовать lateinit, потому что первый вызов if (d == null) сгенерирует.

После процесса ему будут назначены ненулевые данные, но для возврата необходимо использовать !! (оператор двойного взрыва или ненулевое утверждение).

Что лучшеподход, чтобы избежать !!?

fun testGetLowest (dataArray: List<Data>) : Data {
   var d: Data? = null
   for (i in dataArray.indecs) {

       if (d == null) {// first run
           d = dataArray[i]
       } else if {
           d.level < dataArray[i].level
           d = dataArray[i]
       }
    }
    return d!!
}

Ответы [ 5 ]

0 голосов
/ 06 июня 2018

Принятый ответ вполне подходит, но просто упомяну другой способ решения вашей проблемы, изменив одну строку в вашем коде: return d ?: dataArray[0]

0 голосов
/ 06 июня 2018

Обычно вы можете и должны опираться на компилятор, чтобы сделать вывод обнуляемости.Это не всегда возможно, и в надуманном примере, если внутренний цикл выполняется, но один раз d не равен нулю.Это гарантированно произойдет, если dataArray имеет хотя бы одного члена.

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

fun testGetLowest (dataArray: List<Data>) : Data {
   require(dataArray.size > 0, { "Expected dataArray to have size of at least 1: $dataArray")
   var d: Data? = null
   for (i in dataArray.indecs) {

       if (d == null) {// first run
           d = dataArray[i]
       } else if {
           d.level < dataArray[i].level
           d = dataArray[i]
       }
    }
    return checkNotNull(d, { "Expected d to be non-null through dataArray having at least one element and d being assigned in first iteration of loop" })
}

Помните, что вы можете вернуть результат checkNotNull (и аналогичные операторы):

val checkedD = checkNotNull(d)

См. Предварительные условия для Google Guava для получения информации о подобном.

0 голосов
/ 05 июня 2018

Даже если бы вы преобразовали его в Option, вам все равно пришлось бы иметь дело со случаем, когда dataArray пусто, и поэтому возвращаемое значение не определено.

Если вы хотите сделать эту функцию завершенной, а не вызывать исключение, вы можете вернуть Option<Data> вместо Data, чтобы в случае пустого dataArray возвращалось Noneи оставьте это вызывающей стороне, чтобы разобраться с тем, как справиться с грустным путем.

0 голосов
/ 05 июня 2018

Если вам не нравится !!, укажите для него значение по умолчанию.Вы поймете, что можете указать значение по умолчанию только в том случае, если список не пустой, но, как вы сказали, список уже известен как непустой.Хорошая часть этой истории заключается в том, что система типов не отслеживает размер списка, поэтому, когда вы говорите dataArray[0], это повлечет ваше слово.

fun testGetLowest(dataArray: List<Data>) : Data {
    var d: Data = dataArray[0]
    for (i in 1 until dataArray.size) {
        if (d.level < dataArray[i].level) {
            d = dataArray[i]
        }
    }
    return d
}
0 голосов
/ 05 июня 2018

Как сделать ту же проверку и покрыть пустой регистр

fun testGetLowest(dataArray: List<Data>) 
    = dataArray.minBy { it.level } ?: throw AssertionError("List was empty")

При этом оператор ?: используется либо для получения минимума, либо, если минимум равен нулю (список пуст), бросаетвместо этого ошибка.

...