Каков правильный подход, когда функция Котлина не принимает тип NULL

Поэтому я решал проблему Коанса и чрезмерно сложное решение столкнулось с тем, что беспокоило меня. Я использовал функцию Int.compareTo () для типов с нулевым значением. Это «легко», если первый из них является нулевым, потому что я просто пишу:

val a : Int? = 1 val b : Int = 1 a?.compareTo(b) 

Но если b является нулевым, то я не смог заставить его работать, может быть, я что-то пропустил? Итак, что делать, когда это так?

 val a : Int? = 1 val b : Int? = 2 a?.compareTo(b) 

Я получаю синтаксическую ошибку: «Ни одна из следующих функций не может быть вызвана с предоставленными аргументами».

Но, когда я представляю это:

 val a : Int? = 1 val b : Int? = 2 val x : Int = b ?: 0; o1?.compareTo(x) 

Он работает, но кажется, что это не правильный способ сделать это. Есть ли способ лучше?

Ты можешь сделать

 val a: Int? = 1 val b: Int? = 2 b?.let { a?.compareTo(b) } стоит val a: Int? = 1 val b: Int? = 2 b?.let { a?.compareTo(b) } 

let блок будет выполнен, только если b не равен NULL.

Или просто

 if (a != null && b != null) { a.compareTo(b) } 

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

Подпись метода Int.compareTo () не определена для аргументов с нулевым значением, поэтому это невозможно обойтись без обеспечения нулевой безопасности аргумента, например, используя оператор elvis так же, как вы предложили.

Вы должны попытаться реализовать свое решение без ошибок. Но если вы все еще нуждаетесь в этом, и если можно предположить, что null==0 вы не должны использовать ?. вызов метода. Он вернет вам Int? также. Просто сопоставьте оба null числа с 0.

 (a?:0).compareTo(b?:0) 

Единственный лучший способ – реализовать compareTo самостоятельно. По умолчанию сравнение не знает, какой результат вы хотите, если вы сравниваете значение 12 с null или null значением. Он знает, как сравнивать фактические числа. Я думаю, что ваш лучший способ – реализовать поведение, которое вы хотите для работы с null s.

Пример реализации:

 fun main(args: Array<String>) { println(compareNullableInts(null, 2)) // -1 println(compareNullableInts(null, null)) // 0 println(compareNullableInts(2, null)) // 1 println(compareNullableInts(10, 5)) // 1 } fun compareNullableInts(a: Int?, b: Int?): Int { if (a == null && b == null) return 0 if (a == null) return -1 if (b == null) return 1 return a.compareTo(b) } 

выражение должно быть таким:

 val result = b?.let { a?.compareTo(b) ?: -1 } ?: 1; 

Примеры

 > a = 1 b = 2 ---> -1 > a = null b = 2 ---> -1 > a = null b = -1 ---> -1 > a = 1 b = null ---> 1 > a = -1 b = null ---> 1 > a = null b = null ---> 1 // the order is no matter 

ЕСЛИ вы хотите позволить null сравнивать null return 0 тогда выражение немного длиннее:

 val result = b?.let { a?.compareTo(b) ?: -1 } ?: a?.let { 1 } ?: 0; 

Примечание : вам не важно производительность, поскольку функция let является встроенной функцией. что означает, что он генерирует код, как показано ниже в java:

 int result = b != null ? a != null ? a.compareTo(b) : -1 : a != null ? 1 : 0;