Шесть навыков разработки на Kotlin, которые вам нужно знать

Привыкайте писать вместе! Это 13-й день моего участия в «Новом ежедневном плане Nuggets · Апрельское задание по обновлению», нажмите, чтобы просмотреть подробности мероприятия .

1. Оптимизация хвостовой рекурсии

Обычно мы можем столкнуться со сценарием написания рекурсивных функций, таких как:

fun test5(n: Int): Int =
    if (n == 1) {
        1
    } else
        test5(n - 1)
复制代码

Каждый метод соответствует фрейму стека. Рекурсивный вызов метода приведет к тому, что глубина стека метода будет слишком большой, и существует риск OOM. Kotlin обеспечивает 尾递归特性оптимизацию:

tailrec fun test5(n: Int): Int =
    if (n == 1) {
        1
    } else
        test5(n - 1)
复制代码

Видно, что оптимизация хвостовой рекурсии заключается в добавлении в метод tailrec, а вызов рекурсивного метода должен быть в конце метода, декомпилируйте его в java-код, чтобы увидеть эффект:

изображение.png

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

infix2. Реальная борьба инфиксного метода

Модификация инфиксного метода заключается в добавлении infixобъявления к методу, при этом может быть объявлен только один параметр метода, например:

infix fun String.a(b: String) = "$this - $b"
复制代码

Поясним на примере:

У нас обычно есть такое требование:传入文件路径String返回File类型

fun makeFile(parent: String, child: String): File {
    return File(parent, child)
}
复制代码

В таком написании нет ничего плохого, но с помощью инфиксной функции мы можем добиться более элегантной инкапсуляции, как показано ниже:

infix fun String.div(child: String): File = File(this, child)
复制代码

Используйте следующим образом:

fun makeFile(parent: String, child: String): File = parent div child
复制代码

что parent div childэквивалентно File(this, child)реализации .

Это не особенно элегантно для написания, например, приходится каждый раз divсоздавать Fileобъекты , divэто слишком громоздко для написания, а читабельность слишком плохая.

Чтобы решить две вышеупомянутые проблемы, мы можем объединить перегрузку операторов operatorдля дальнейшей оптимизации.Давайте посмотрим на общие функции перегрузки операторов и отношения отображения соответствующих операторов:

выражение перерабатывать
а + б а. плюс (б)
а - б а.минус(б)
а * б раз (б)
а/б а.дел(б)
а % б а. мод (б)
а..б a.rangeTo (б)

Среди них есть оператор divперегрузки функции /, с помощью которого мы преобразуем функцию String в File выше:

infix operator fun String.div(child: String): File = File(this, child)
复制代码

Затем его можно использовать следующим образом:

fun makeFile(parent: String, child: String): File = parent / child
复制代码

Как видно выше, parent / childсоздание файла может быть выполнено напрямую, и /читабельность выше.

рекомендация

отjuejin.im/post/7086234211333439519