0Pricing
Kotlin Academy · Lekcja

Budowanie API podobnych do DSL

Używaj infix dla większej przejrzystości

Budowanie API podobnych do DSL to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Składnia infiksowa dla czytelności

Funkcje infiksowe są jednym z elementów składowych DSL-i Kotlina (języków dziedzinowych). Sprawiają, że wywołania API przypominają naturalne zwroty.

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

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

Pomysł na płynny konstruktor

Połączenie składni infiksowej z małymi typami pozwala deklaratywnie wyrażać intencje.

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

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

Konfiguracja oparta na parach

Infiksowa funkcja to umożliwia tworzenie czytelnych map konfiguracyjnych.

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

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

DSL zakresów

Dzięki składni infiksowej konstruktory zakresów przypominają język naturalny.

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

Łączenie warunków

Za pomocą funkcji infiksowych można tworzyć czytelne wyrażenia przypominające zwroty logiczne.

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)
}

Lambdy z receiverem

Prawdziwe DSL-e często łączą składnię infiksową z lambdami mającymi receiver, dzięki czemu blok może bezpośrednio konfigurować obiekt.

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)
}

Wyjaśnienie lambd z receiverem

Typ funkcji taki jak Html.() -> Unit sprawia, że blok jest wykonywany tak, jakby znajdował się wewnątrz instancji Html, więc do elementów składowych można odwoływać się bez prefiksu.

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 jako mały DSL

Standardowa funkcja apply sama jest DSL-em opartym na lambdzie z receiverem, służącym do konfigurowania obiektu.

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

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

Zachowuj czytelność DSL-i

Dobry DSL ogranicza zbędne elementy. Wybieraj nazwy, dzięki którym miejsce wywołania opisuje intencję.

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)
}

Składnia infiksowa i lambda

Połączenie funkcji infiksowych z lambdami pozwala tworzyć ekspresywne konstruktory.

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)
}

Kiedy budować DSL

DSL-e sprawdzają się przy powtarzalnej, strukturalnej konfiguracji (interfejsów użytkownika, konstruktorów i testów). W przypadku jednorazowej logiki zwykłe funkcje są prostsze.

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

Szybkie sprawdzenie

Sprawdź swoją wiedzę na temat interfejsów API przypominających DSL.

Podsumowanie

Opanowali Państwo tworzenie interfejsów API przypominających DSL:

  • Funkcje infiksowe sprawiają, że wywołania przypominają naturalne zwroty.
  • Lambdy z receiverem (Type.() -> Unit) pozwalają blokom bezpośrednio konfigurować obiekty.
  • apply i buildList to DSL-e biblioteki standardowej.
  • Używaj DSL-i do strukturalnej, powtarzalnej konfiguracji i dbaj o ich czytelność.
class C { var x = 0 }
fun c(b: C.() -> Unit) = C().apply(b)

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

Często zadawane pytania

Czy lekcja „Budowanie API podobnych do DSL” jest bezpłatna?

Tak — pełny tekst „Budowanie API podobnych do DSL” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Budowanie API podobnych do DSL”?

Używaj infix dla większej przejrzystości Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?

Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Budowanie API podobnych do DSL”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?

Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Funkcje infiksowe
  2. Budowanie API podobnych do DSL
  3. Funkcje tailrec
  4. Kiedy używać poszczególnych rozwiązań
← Powrót do Kotlin Academy