Intereting Posts
Изменение высоты списка элементов при установке элемента изображения Почему компилятор Kotlin требует явного инициализатора свойства var? Статус состояния Vault для UNONSUMED / CONSUMED Kotlin – Самый идиоматический способ преобразования списка в MutableList Связывание данных Kotlin Android studio errors Разница между «*» и «Any» в генериках Котлина Хороший способ доступа к смешанным 8/16/32-битным словам Как установитьOnNavigationItemListener в BottomNavigationView в android с помощью Kotlin? Как получить javaclass из массива java-типа в Котлине? Почему существует разница между сборщиками coroutine для CompletableFuture и ListenableFuture? Разрешение конфигурации «debugCompile» напрямую запрещено Как добавить поддержку градиента для проекта TestNG Kotlin? Не удалось обновить значение параметра параметра метода Котлин Стандартное отклонение Kotlin с дженериками В чем разница между нормальным классом и классом данных в котлине

Сравнение двух вариантов в Котлине

Рассмотрим класс с полем id, который может быть пустым до тех пор, пока не будет сохранен в базе данных:

class IdableK<T : IdableK<T>> : Comparable<T> { private var id : Long? = null } 

Я пытаюсь реализовать метод compareTo следующим образом:

  override fun compareTo(other: T): Int { if (id == null) { return -1; } if (other.id == null) { return 1; } return id!!.compareTo(other.id!!) } 

Правильно ли это? Был бы простой способ сделать это?

Проверьте пакет kotlin.comparisons . Например, вы можете использовать compareValues :

 class IdableK<T : IdableK<T>> : Comparable<T> { private var id: Long? = null override fun compareTo(other: T) = compareValues(id, other.id) } 

Это неверно. Если у вас есть два экземпляра с их идентификаторами, равными null , оба экземпляра будут возвращать -1 при вызове compareTo(other) на них, а если один возвращает -1 другой должен вернуть 1 в правильной реализации. Я не уверен, есть ли ситуации, когда имеет смысл реализовать compareTo на основе свойств с возможностью NULL, но я не могу себе представить. Может быть, для вас тоже лучший способ?

Кроме того, вы должны избегать ненулевых утверждений ( !! ). Поскольку вы используете var s, другие потоки могут изменять значение до нуля, так что, даже если вы делали нулевую проверку раньше, значение теперь равно null и !! броски. Вместо этого вы должны сохранить оба идентификатора в локальных переменных и проверить их для null значений.

Если вам абсолютно необходимо использовать compareTo , я бы сделал это следующим образом:

 override fun compareTo(other: T): Int { val thisId = id val otherId = other.id if (thisId == null && otherId == null) return 0 if (thisId == null && otherId != null) return -1 if (thisId != null && otherId == null) return 1 // thisId and otherId are now smart cast to Long return thisId.compareTo(otherId) } 

Вот простой способ:

 override fun compareTo(other: T) :Int { return id?.compareTo(other.id ?: return 1) ?: -1 } 

Однако этот фрагмент кода очень недружелюбен к начинающему программисту kotlin. Это предполагает слишком много волшебства, которые делают его похожим на scala. Эти три вопросительных вопроса заставляют людей озадачиваться, по крайней мере, они должны подумать минутку или два, прежде чем они смогут понять, что происходит в этом минималистическом лайнере. Я по-прежнему предпочитаю ваше издание. Это более подробный, но ясный.

И я действительно беспокоюсь о симметричной проблеме. Это имеет значение, и это не просто проблема дизайна. Если вы не сравниваете свойства с нулевым значением, такой головоломки программирования не будет. Это будет просто override fun compareTo(other: T) = id.compareTo(other.id) . Простой, понятный и не вводящий в заблуждение.

Я предпочел бы выбросить весь нулевой код проверки и просто жить с этими нулевыми утверждениями. Потому что в основном вы не будете сравнивать там вещи, пока они не будут полностью инициализированы. Если это утверждение терпит неудачу, это означает, что что-то действительно плохое происходит.

О, BTW, я не знаю о вашем проекте, и если он попадает в редкие случаи, когда вам приходится сравнивать свойства с нулевыми значениями, я думаю, вы могли бы написать специальную версию Comparator которая учитывала бы нули вместо того, чтобы бросать NPE. Не связывайтесь с естественным порядком.