суббота, 11 июля 2015 г.

Kotlin @ Hackathon

Завершился сорока восьми часовой марафон программирования, на котором я изучал язык Kotlin и писал известно что, а ведь до этого события я его и в глаза не видел.

Первые часов 20 прошли очень результативно, после чего пришлось пойти поспать в комнату отдыха. После обеда работа шла медленно и печально, поэтому я решил поехать домой и выспаться. Сегодня с утра полировал код и пытался найти ошибку в алгоритме подсчёта очков, из-за которой он долго думает, но плохо играет. Ещё не успел портировать Пашкин код.

Язык Kotlin мне понравился. Подобно JavaFX он сильно уменьшает количество boilerplate кода. С другой стороны, код становится плотным и насыщенным, поэтому лучше добавлять комментарии.
  data class Player(val id: Int,
                        name: String?,
                    val solver: Solver? = null) {
      val name = solver?.name ?: name ?: "Player ${id + 1}"
  }
Например, код выше является описанием класса с тремя readonly свойствами id, name и solver, для поддержки которых генерятся методы equals и hashCode.

Конструктор по-умолчанию имеет два обязательных и один опциональный параметр со значением null по умолчанию. String? означает, что параметр типа String может принимать значение null.

Свойство name задаётся не напрямую через конструктор, а на основе выражения, в котором присутствует куча проверок на null. Сначала мы спрашиваем имя solver?.name, которое вернёт null, если сам solver тоже null.

Потом идёт так называемый elvis-оператор, который возвращает левую часть, если она не null, иначе возвращает правую.

Тип свойства name напрямую не задан, а определяется из выражения. С учётом всех проверок на null, типом оказывается String, а не String?, как у соответствующего параметра.

Методы так и подмывает писать однострочными:
  fun count(id: Int) = cells.values().filter { it == id }.size()
Да, λямбды поддерживаются. Кстати, тип объекта внутри if определяется автоматически, если в if этот тип проверялся.

Поддержка range сделана простой и оптимальной в коде:
  x in 1..width && y in 1..height
Кроме того, мне очень понравились функции расширения. Обычно в Java заводят вспомогательный класс с набором статических методов, а тут можно написать следующим образом:
  fun JComponent.getInnerBounds(): Rectangle {
      val bounds = Rectangle(getWidth(), getHeight())
      val insets = getInsets()
      if (insets != null) {
          bounds.x += insets.left
          bounds.y += insets.top
          bounds.width -= insets.left + insets.right
          bounds.height -= insets.top + insets.bottom
      }
      return bounds
  }
После чего можно использовать этот метод, будто он объявлен в классе JComponent. В целом, поддержка Java отличная.

В общем, интересный опыт. Теперь надо готовить презентацию.

2 комментария: