После сообщения о представлении ADT на четырех разных языках: Scala, Haskell, Rust и TypeScript я задумался о том, как это будет работать в мире Kotlin.
Итак, сначала нам нужно определить наш тип данных. Мы возьмем Tree по двум причинам:
- В исходной статье во всех примерах используются деревья, поэтому мы могли сравнивать яблоки с яблоками или деревья с деревьями.
- Он рекурсивный, поэтому с ним интересно работать.
Запечатанные классы Kotlin - это распространенный способ реализации ADT.
Сначала давайте посмотрим на реализацию, а затем подробно обсудим, как это работает:
Итак, наш общий интерфейс Tree
. Поскольку это общая структура данных, мы определяем ее с помощью параметра типа: Tree<T>
. Мы также используем аннотацию out
отклонения, чтобы указать, что этот тип ковариантен. Далее мы обсудим, почему.
Поскольку все пустые деревья одинаковы, мы объявляем Empty
одноэлементным объектом, расширяющим Tree<Nothing>()
.
Существует много путаницы между Any
, Nothing
и <*>
(также называемой звездной проекцией). В этом случае звездная проекция просто не сработает. Но вы можете определить Empty
как Tree<Any>()
, и он будет компилироваться. На следующем шаге мы увидим, почему это ошибка.
Теперь давайте посмотрим на класс Node
. Имеет большой смысл определить его как класс данных, поскольку он предоставит нам, по крайней мере, хороший toString()
метод.
Обратите внимание, как мы указываем значения по умолчанию для свойств left
и right
:
val left: Tree<T> = Empty
Здесь в игру вступают как ковариация, так и Nothing
.
Независимо от того, к какому типу принадлежит наш T
, Nothing
находится внизу иерархии классов, поэтому его можно использовать.
Это печатает:
Node(value=42, left=Empty, right=Node(value=62, left=Empty, right=Empty))
Благодаря параметрам по умолчанию нам не нужно было указывать left
и right
для листового узла, что приятно.
Но печать в целом не так уж и интересна.
Как насчет того, чтобы просуммировать значения всех узлов?
В этом реальная сила ADT в целом и закрытых классов Kotlin в частности.
Поскольку наши классы запечатаны, выражение when
является исчерпывающим и кратким.
println(tree.sum()) // 104
Выводы
- Котлин предоставляет хорошие возможности для реализации ADT
- Используйте
object
, если у вашего варианта нет состояния - В противном случае отдавайте предпочтение
data class
when
expression - это мощный инструмент для работы с ADT в Kotlin
Больше чтения:
Kotlin и алгебраические типы данных
Поскольку Kotlin неуклонно распространяется в массы, все больше и больше разработчиков Java знакомятся с« новыми концепциями, которые были… medium.com »