0Pricing
Kotlin Academy · Урок

Создание API в стиле DSL

Используйте инфиксную запись для ясности

«Создание API в стиле DSL» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.

Инфиксные функции для ясности

Инфиксные функции — один из строительных блоков DSL Kotlin, то есть предметно-ориентированных языков. Они позволяют читать вызовы API как естественные фразы.

infix fun String.eq(value: String) = this == value

fun main() {
    println("on" eq "on")
}

Идея выразительного построителя

Сочетание инфиксных функций с небольшими типами позволяет декларативно выражать намерение.

class Query(val field: String) {
    infix fun equals(value: String) = "$field = '$value'"
}

fun main() {
    val q = Query("name") equals "Sam"
    println(q)
}

Конфигурация на основе пар

Инфиксная функция to помогает создавать легко читаемые карты конфигурации.

fun configure(vararg opts: Pair<String, Any>) = opts.toMap()

fun main() {
    val cfg = configure("debug" to true, "level" to 3)
    println(cfg)
}

DSL диапазонов

Благодаря инфиксным функциям построители диапазонов читаются почти как английские фразы.

fun main() {
    val r = 1 until 10 step 2
    println(r.toList())
}

Объединение условий

С помощью инфиксных функций можно составлять выразительные фразы, похожие на логические условия.

data class Rule(val ok: Boolean) {
    infix fun and(other: Rule) = Rule(ok && other.ok)
}

fun main() {
    val result = Rule(true) and Rule(false)
    println(result.ok)
}

Лямбды с получателями

Настоящие DSL часто сочетают инфиксные функции с лямбдами, у которых есть получатели, позволяя блоку напрямую настраивать объект.

class Html {
    val parts = mutableListOf<String>()
    fun p(text: String) { parts.add("<p>$text</p>") }
}

fun html(block: Html.() -> Unit): Html {
    val h = Html()
    h.block()
    return h
}

fun main() {
    val page = html { p("Hi") }
    println(page.parts)
}

Как работают лямбды с получателем

Тип функции вроде Html.() -> Unit заставляет блок выполняться так, словно он находится внутри экземпляра Html, поэтому к его членам можно обращаться без префикса.

class Box { var value = 0 }

fun box(init: Box.() -> Unit): Box {
    val b = Box()
    b.init()
    return b
}

fun main() {
    val b = box { value = 42 }
    println(b.value)
}

apply как мини-DSL

Стандартная функция apply сама является DSL на основе лямбды с получателем для настройки объекта.

class Server {
    var host = ""
    var port = 0
}

fun main() {
    val s = Server().apply {
        host = "localhost"
        port = 8080
    }
    println("${s.host}:${s.port}")
}

Сохраняйте читаемость DSL

Хороший DSL сводит лишний шум к минимуму. Отдавайте предпочтение именам, благодаря которым место вызова читается как описание намерения.

data class Style(var bold: Boolean = false)

fun style(block: Style.() -> Unit) = Style().apply(block)

fun main() {
    val s = style { bold = true }
    println(s.bold)
}

Инфиксная функция и лямбда

Сочетание инфиксных функций с лямбдами позволяет создавать выразительные построители.

class Table {
    val rows = mutableListOf<String>()
    infix fun row(text: String) { rows.add(text) }
}

fun table(block: Table.() -> Unit) = Table().apply(block)

fun main() {
    val t = table {
        row("A")
        row("B")
    }
    println(t.rows)
}

Когда стоит создавать DSL

DSL особенно полезны для повторяющейся структурированной конфигурации: пользовательских интерфейсов, построителей и тестов. Для разовой логики обычные функции проще.

fun main() {
    val list = buildList {
        add(1)
        add(2)
    }
    println(list)
}

Быстрая проверка

Проверьте, насколько хорошо Вы поняли API, похожие на DSL.

Итоги

Вы научились создавать API, похожие на DSL:

  • Инфиксные функции позволяют читать вызовы как фразы.
  • Лямбды с получателем (Type.() -> Unit) позволяют блокам напрямую настраивать объекты.
  • apply и buildList — это DSL стандартной библиотеки.
  • Используйте DSL для структурированной повторяющейся конфигурации и сохраняйте их читаемость.
class C { var x = 0 }
fun c(b: C.() -> Unit) = C().apply(b)

fun main() {
    println(c { x = 9 }.x)
}

Часто задаваемые вопросы

Урок «Создание API в стиле DSL» бесплатный?

Да — полный текст урока «Создание API в стиле DSL» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.

Чему я научусь в уроке «Создание API в стиле DSL»?

Используйте инфиксную запись для ясности Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Kotlin Academy?

Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Создание API в стиле DSL»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Kotlin Academy?

Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Инфиксные функции
  2. Создание API в стиле DSL
  3. Функции tailrec
  4. Когда что использовать
← Назад к Kotlin Academy