Как стать автором
Обновить

Комментарии 42

Насчёт работы с датами — можно было чуть большим количеством кода получить даже более красивые результаты


data class IntervalInfo(amount: Long, type: ChronoUnit)
operator fun Date.minus(interval: IntervalInfo):Date{…}
operator fun Date.plus(interval: IntervalInfo):Date{…}
val Int.months = IntervalInfo(this, ChronoUnit.MONTHS)
val Int.days = IntervalInfo(this, ChronoUnit.DAYS)

и использовать как-то вроде


val before = date - 3.days
val after = date + 2.months

Ну а если вы не на 8й джаве пока — тогда можно свой аналогийчный энам изобрести.

Мне не очень понравилась мысль перегружать примитивы. Это хорошо для DSL, но в продакшен коде будет приводить к проблемам, так как на days и months не остановишься, и скоро у простого Int будет api не меньше чем у list
Ну они не сами же вам в код попадают. Где надо — там заимпортировали, где не надо — не импортируете. То есть в том месте где у вас будет работа с датами — там и будете красивый код писать.
Да, только IDE будет подсказывать все. Проверил
Мне кажется что если оно к месту — то почему бы не писать красиво там где можно писать красиво?
Может, это чопорно, но по мне Int не должен знать о ChronoUnit, Date и прочем. Написав такой extension, мы расширяем api Int такими знаниями.
Вариант ниже решает эту проблему: DAYS знает о Int, но не наоборот.

Красиво — это не пихать мульйон методов в один тип. Любой нубас может наговнокодить божественных и несолидных объектов, когда это красивым стало?

Ну не знаю. Должен ли Int знать про Long? А про BigInteger? В котлине знает. По мне — это просто удобные эксплицитные конвертеры.

Но в общем можно и не использовать свой data-класс, а писать как-то вроде


val before = date - Pair(3, DAYS)
Тогда возвращаясь к локаничности, но без перегрузки примитивов. Я, навреное, на это перепишу свой код
val before = date - DAYS*3
before = date - 3.days

выглядит вполне в духе Ruby.

а чем отличаются
val list1: List?
и
var list9: List?
Тем, что первый нельзя заменять после инициализации. В случае с локальной переменной var нужен не часто, а вот в случае поля — вполне.

Возможно, rfq не заметил, что там разные ключевые слова

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

Видимо, упор идёт на то, что IDEA заметно выделяет локальные переменные с var.

Отвратительные ключевые слова — сливаются воедино, я тоже не сразу заметил, что первое слово в примере то разное! Очень неприятное решение от языка, который стремится уменьшить количество ошибок. Лучше бы какое-нибудь "var/let" заюзали

Сорри, это было в предыдущую ветку сообщение

возможно, взяли пример со scala
Ага, в Скала это настолько же ужасно.

А чем "невозможный на Java" пример с assertFail отличается от использования @Test(expected = ArrayIndexOutOfBoundsException.class)?

Я бы спросил по-другому. Чем с точки зрения красоты отличаются вот эти две строчки:


Kotlin: assertFail<ArrayIndexOutOfBoundsException> { arrayOf(1, 2)[3] }
Java: assertFail(ArrayIndexOutOfBoundsException.class, () -> arrayOf(1, 2)[3])

наверное тем, что конструкция на Java будет жить только в JVM начиная с 8 версии, а на Kotlin и в JVM 7 и даже 6?

Согласен, не слишком удачный пример. В куске кода чуть выше (про репозиотрии) был более инетересный вариант (сейчас продублирую в статье). Это в случае, если класс писал не ты и T просто нет.
inline fun <reified T, ID: Serializable> CrudRepository<T, ID>.find(id: ID): T {
    return findOne(id) ?: throw ObjectNotFound(id, T::class.qualifiedName)
}

Я бы разделил немного по-другому. Важно не то, писал ли ты класс — а то, может ли параметр шаблона быть выведен из параметра функции. Если может — то Kotlin дает более красивый код чем Java. Если нет — то и разницы нет.


В примере с репозиторием параметр шаблона T выводится из скрытого параметра метода this (вроде бы).

Это inline функция, она не существует в runtime, вместо этого она разворачивается при компиляции в месте использования. Поэтому, T доступно — в compile time она ещё не стерта

Причем тут это?

В примере с репозиторием параметр шаблона T выводится из скрытого параметра метода this (вроде бы).

Решил объяснить как работает эта магия. Из this T в общем случае не выведешь, насколько я помню. Я когда-то пробовал, решил что легче каким-то образом передавать Class T. Источник

Если this имеет тип CrudRepository<T, ID> — то для компилятора нет проблем "достать" из него T.

В случае assertFail это не сработает, так как нет объекта, из которого можно вытащить T. А механизм один.

Так я про это и говорю! Именно поэтому при вызове assertFail нужно явно писать тип в угловых скобках, а при вызове find — не нужно.


А это, в свою очередь, приводит к тому, что assertFail на Kotlin выходит ничуть не красивее чем аналог на Java. Функция же find на Kotlin получается красивее чем на Java, потому что у нее "исчезает" один параметр.

Groovy ни чем не хуже… Даже Веселей...

Кроме отсутсвия статической типизации, что не делает его Safe, что для меня является основным приемуществом языка

Ожидал более практических результатов в этой статье.
Я, например, пробовал компиляцию в js — как proof-of-concept интересно, но тулинг и поддержка студии (основы "философии") — отвратительные, их практически нет.


Некоторые идеи, представленные здесь — далеко не новые, а уже давно "витают" в сообществе. В Kotlin'е просто использованы свежие идеи. Но от влияния Java он никуда не денется: на некоторые issue JetBrains так и говорит: мы сделали это так, потому что это так в Java.

Практический результат — написанный проект мне нравиться, язык действительно помогает сделать код безопаснее, код хорошо читается. К сожалению, влияние в мелочах, поэтому ужать всё это в одну статью не получилось.
НЛО прилетело и опубликовало эту надпись здесь
Я полгода пишу на Kotlin, и всё что смог припомнить:
1. Extension написанный на Kotlin нельзя вызвать из Java. Было бы странно, если бы можно было.
2. Если написать на Kotlin класс и отнаследоваться от него на Java, могут возникнуть некоторые сложности.
НЛО прилетело и опубликовало эту надпись здесь
У меня проект на Spring Boot, Hibernate и JSF, final решается на раз плагином
С интерфесами вряд ли будут проблемы, я говорил про наследование классов.
Насчет 100% — да, я не стал это упоминать в статье и не считаю это «нарушением интеропа», так как причиной этому то, что в Kotlin немного больший функционал (в основном, за счет компилятора), чем в Java, и, естественно, к нему нет прямого доступа из Java.
а еще косяки с дженериками
Это вы о чем?

метод с inline + reified из java не вызвать. Интерфейс определенный в java это SAM, но, внезапно, интерфейс определенный в kotlin нет. В интерфейсах @JvmStatic/@JvmField не работает и тд. В какой-то степени это должно радовать, потому что в котлине есть фичи, которые невозможно повторить в джаве, но тогда нужно быть скромнее про 100% интероп.

Сам ещё не использовал, но, судя по всему, это может сильно изменить подход к многопоточному программированию.

Не совсем ясно причем тут многопоточное программирование…

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации